/**
 * usePopAction - POP 액션 실행 React 훅
 *
 * executePopAction (순수 함수)를 래핑하여 React UI 관심사를 처리:
 *   - 로딩 상태 (isLoading)
 *   - 확인 다이얼로그 (pendingConfirm)
 *   - 토스트 알림
 *   - 후속 액션 체이닝 (followUpActions)
 *
 * 사용처:
 *   - PopButtonComponent (메인 버튼)
 *
 * pop-string-list 등 리스트 컴포넌트는 executePopAction을 직접 호출하여
 * 훅 인스턴스 폭발 문제를 회피함.
 */

import { useState, useCallback, useRef } from "react";
import type {
  ButtonMainAction,
  FollowUpAction,
  ConfirmConfig,
} from "@/lib/registry/pop-components/pop-button";
import { usePopEvent } from "./usePopEvent";
import { executePopAction } from "./executePopAction";
import type { ActionResult } from "./executePopAction";
import { toast } from "sonner";
import { showErrorToast } from "@/lib/utils/toastUtils";

// ========================================
// 타입 정의
// ========================================

/** 확인 대기 중인 액션 상태 */
export interface PendingConfirmState {
  action: ButtonMainAction;
  rowData?: Record<string, unknown>;
  fieldMapping?: Record<string, string>;
  confirm: ConfirmConfig;
  followUpActions?: FollowUpAction[];
}

/** execute 호출 시 옵션 */
interface ExecuteActionOptions {
  /** 대상 행 데이터 */
  rowData?: Record<string, unknown>;
  /** 필드 매핑 */
  fieldMapping?: Record<string, string>;
  /** 확인 다이얼로그 설정 */
  confirm?: ConfirmConfig;
  /** 후속 액션 */
  followUpActions?: FollowUpAction[];
}

// ========================================
// 상수
// ========================================

/** 액션 성공 시 토스트 메시지 */
const ACTION_SUCCESS_MESSAGES: Record<string, string> = {
  save: "저장되었습니다.",
  delete: "삭제되었습니다.",
  api: "요청이 완료되었습니다.",
  modal: "",
  event: "",
};

// ========================================
// 메인 훅
// ========================================

/**
 * POP 액션 실행 훅
 *
 * @param screenId - 화면 ID (이벤트 버스 연결용)
 * @returns execute, isLoading, pendingConfirm, confirmExecute, cancelConfirm
 */
export function usePopAction(screenId: string) {
  const [isLoading, setIsLoading] = useState(false);
  const [pendingConfirm, setPendingConfirm] = useState<PendingConfirmState | null>(null);

  const { publish } = usePopEvent(screenId);

  // publish 안정성 보장 (콜백 내에서 최신 참조 사용)
  const publishRef = useRef(publish);
  publishRef.current = publish;

  /**
   * 실제 실행 (확인 다이얼로그 이후 or 확인 불필요 시)
   */
  const runAction = useCallback(
    async (
      action: ButtonMainAction,
      rowData?: Record<string, unknown>,
      fieldMapping?: Record<string, string>,
      followUpActions?: FollowUpAction[]
    ): Promise<ActionResult> => {
      setIsLoading(true);

      try {
        const result = await executePopAction(action, rowData, {
          fieldMapping,
          screenId,
          publish: publishRef.current,
        });

        // 결과에 따른 토스트
        if (result.success) {
          const msg = ACTION_SUCCESS_MESSAGES[action.type];
          if (msg) toast.success(msg);
        } else {
          showErrorToast("작업에 실패했습니다", result.error, { guidance: "잠시 후 다시 시도해 주세요." });
        }

        // 성공 시 후속 액션 실행
        if (result.success && followUpActions?.length) {
          await executeFollowUpActions(followUpActions);
        }

        return result;
      } finally {
        setIsLoading(false);
      }
    },
    [screenId]
  );

  /**
   * 후속 액션 실행
   */
  const executeFollowUpActions = useCallback(
    async (actions: FollowUpAction[]) => {
      for (const followUp of actions) {
        switch (followUp.type) {
          case "event":
            if (followUp.eventName) {
              publishRef.current(followUp.eventName, followUp.eventPayload);
            }
            break;

          case "refresh":
            // 새로고침 이벤트 발행 (구독하는 컴포넌트가 refetch)
            publishRef.current("__pop_refresh__");
            break;

          case "navigate":
            if (followUp.targetScreenId) {
              publishRef.current("__pop_navigate__", {
                screenId: followUp.targetScreenId,
                params: followUp.params,
              });
            }
            break;

          case "close-modal":
            publishRef.current("__pop_modal_close__");
            break;
        }
      }
    },
    []
  );

  /**
   * 외부에서 호출하는 실행 함수
   * confirm이 활성화되어 있으면 pendingConfirm에 저장하고 대기.
   * 비활성화이면 즉시 실행.
   */
  const execute = useCallback(
    async (
      action: ButtonMainAction,
      options?: ExecuteActionOptions
    ): Promise<ActionResult> => {
      const { rowData, fieldMapping, confirm, followUpActions } = options || {};

      // 확인 다이얼로그 필요 시 대기
      if (confirm?.enabled) {
        setPendingConfirm({
          action,
          rowData,
          fieldMapping,
          confirm,
          followUpActions,
        });
        return { success: true }; // 대기 상태이므로 일단 success
      }

      // 즉시 실행
      return runAction(action, rowData, fieldMapping, followUpActions);
    },
    [runAction]
  );

  /**
   * 확인 다이얼로그에서 "확인" 클릭 시
   */
  const confirmExecute = useCallback(async () => {
    if (!pendingConfirm) return;

    const { action, rowData, fieldMapping, followUpActions } = pendingConfirm;
    setPendingConfirm(null);

    await runAction(action, rowData, fieldMapping, followUpActions);
  }, [pendingConfirm, runAction]);

  /**
   * 확인 다이얼로그에서 "취소" 클릭 시
   */
  const cancelConfirm = useCallback(() => {
    setPendingConfirm(null);
  }, []);

  return {
    execute,
    isLoading,
    pendingConfirm,
    confirmExecute,
    cancelConfirm,
  } as const;
}
