/**
 * 스케줄 자동 생성 서비스
 *
 * 이벤트 버스 기반으로 스케줄 자동 생성을 처리합니다.
 * - TABLE_SELECTION_CHANGE 이벤트로 선택 데이터 추적
 * - SCHEDULE_GENERATE_REQUEST 이벤트로 생성 요청 처리
 * - SCHEDULE_GENERATE_APPLY 이벤트로 적용 처리
 */

import { useState, useEffect, useCallback, useRef } from "react";
import { v2EventBus } from "../events/EventBus";
import { V2_EVENTS } from "../events/types";
import type { ScheduleType, V2ScheduleGenerateRequestEvent, V2ScheduleGenerateApplyEvent } from "../events/types";
import { apiClient } from "@/lib/api/client";
import { toast } from "sonner";
import { showErrorToast } from "@/lib/utils/toastUtils";

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

/** 스케줄 생성 설정 */
export interface ScheduleGenerationConfig {
  // 스케줄 타입
  scheduleType: ScheduleType;

  // 소스 설정
  source: {
    tableName: string; // 소스 테이블명
    groupByField: string; // 그룹화 기준 필드 (part_code)
    quantityField: string; // 수량 필드 (order_qty, balance_qty)
    dueDateField?: string; // 납기일 필드 (선택)
  };

  // 리소스 매핑 (타임라인 Y축)
  resource: {
    type: string; // 'ITEM', 'MACHINE', 'WORKER' 등
    idField: string; // part_code, machine_code 등
    nameField: string; // part_name, machine_name 등
  };

  // 생성 규칙
  rules: {
    leadTimeDays?: number; // 리드타임 (일)
    dailyCapacity?: number; // 일일 생산능력
    workingDays?: number[]; // 작업일 [1,2,3,4,5] = 월~금
    considerStock?: boolean; // 재고 고려 여부
    stockTableName?: string; // 재고 테이블명
    stockQtyField?: string; // 재고 수량 필드
    safetyStockField?: string; // 안전재고 필드
  };

  // 타겟 설정
  target: {
    tableName: string; // 스케줄 테이블명 (schedule_mng 또는 전용 테이블)
  };
}

/** 미리보기 결과 */
export interface SchedulePreviewResult {
  toCreate: any[];
  toDelete: any[];
  toUpdate: any[];
  summary: {
    createCount: number;
    deleteCount: number;
    updateCount: number;
    totalQty: number;
  };
}

/** 훅 반환 타입 */
export interface UseScheduleGeneratorReturn {
  // 상태
  isLoading: boolean;
  showConfirmDialog: boolean;
  previewResult: SchedulePreviewResult | null;

  // 핸들러
  handleConfirm: (confirmed: boolean) => void;
  closeDialog: () => void;
}

// ============================================================================
// 유틸리티 함수
// ============================================================================

/** 기본 기간 계산 (현재 월) */
function getDefaultPeriod(): { start: string; end: string } {
  const now = new Date();
  const start = new Date(now.getFullYear(), now.getMonth(), 1);
  const end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
  return {
    start: `${start.getFullYear()}-${String(start.getMonth() + 1).padStart(2, "0")}-${String(start.getDate()).padStart(2, "0")}`,
    end: `${end.getFullYear()}-${String(end.getMonth() + 1).padStart(2, "0")}-${String(end.getDate()).padStart(2, "0")}`,
  };
}

// ============================================================================
// 스케줄 생성 서비스 훅
// ============================================================================

/**
 * 스케줄 자동 생성 훅
 *
 * @param scheduleConfig 스케줄 생성 설정
 * @returns 상태 및 핸들러
 *
 * @example
 * ```tsx
 * const config: ScheduleGenerationConfig = {
 *   scheduleType: "PRODUCTION",
 *   source: { tableName: "sales_order_mng", groupByField: "part_code", quantityField: "balance_qty" },
 *   resource: { type: "ITEM", idField: "part_code", nameField: "part_name" },
 *   rules: { leadTimeDays: 3, dailyCapacity: 100 },
 *   target: { tableName: "schedule_mng" },
 * };
 *
 * const { showConfirmDialog, previewResult, handleConfirm } = useScheduleGenerator(config);
 * ```
 */
export function useScheduleGenerator(scheduleConfig?: ScheduleGenerationConfig | null): UseScheduleGeneratorReturn {
  // 상태
  const [selectedData, setSelectedData] = useState<any[]>([]);
  const [previewResult, setPreviewResult] = useState<SchedulePreviewResult | null>(null);
  const [showConfirmDialog, setShowConfirmDialog] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const currentRequestIdRef = useRef<string>("");
  const currentConfigRef = useRef<ScheduleGenerationConfig | null>(null);

  // 1. 테이블 선택 데이터 추적 (TABLE_SELECTION_CHANGE 이벤트 수신)
  useEffect(() => {
    const unsubscribe = v2EventBus.subscribe(V2_EVENTS.TABLE_SELECTION_CHANGE, (payload) => {
      // scheduleConfig가 있으면 해당 테이블만, 없으면 모든 테이블의 선택 데이터 저장
      if (scheduleConfig?.source?.tableName) {
        if (payload.tableName === scheduleConfig.source.tableName) {
          setSelectedData(payload.selectedRows);
          console.log("[useScheduleGenerator] 선택 데이터 업데이트 (특정 테이블):", payload.selectedCount, "건");
        }
      } else {
        // scheduleConfig가 없으면 모든 테이블의 선택 데이터를 저장
        setSelectedData(payload.selectedRows);
        console.log("[useScheduleGenerator] 선택 데이터 업데이트 (모든 테이블):", payload.selectedCount, "건");
      }
    });
    return unsubscribe;
  }, [scheduleConfig?.source?.tableName]);

  // 2. 스케줄 생성 요청 처리 (SCHEDULE_GENERATE_REQUEST 수신)
  useEffect(() => {
    const unsubscribe = v2EventBus.subscribe(
      V2_EVENTS.SCHEDULE_GENERATE_REQUEST,
      async (payload: V2ScheduleGenerateRequestEvent) => {
        console.log("[useScheduleGenerator] SCHEDULE_GENERATE_REQUEST 수신:", payload);

        // 이벤트에서 config가 오면 사용, 없으면 기존 scheduleConfig 또는 기본 config 사용
        const configToUse = (payload as any).config ||
          scheduleConfig || {
            // 기본 설정 (생산계획 화면용)
            scheduleType: payload.scheduleType || "PRODUCTION",
            source: {
              tableName: "sales_order_mng",
              groupByField: "part_code",
              quantityField: "balance_qty",
              dueDateField: "delivery_date", // 기준일 필드 (납기일)
            },
            resource: {
              type: "ITEM",
              idField: "part_code",
              nameField: "part_name",
            },
            rules: {
              leadTimeDays: 3,
              dailyCapacity: 100,
            },
            target: {
              tableName: "schedule_mng",
            },
          };

        console.log("[useScheduleGenerator] 사용할 config:", configToUse);

        // scheduleType이 지정되어 있고 config도 있는 경우, 타입 일치 확인
        if (scheduleConfig && payload.scheduleType && payload.scheduleType !== scheduleConfig.scheduleType) {
          console.log("[useScheduleGenerator] scheduleType 불일치, 무시");
          return;
        }

        // sourceData: 이벤트 페이로드 > 상태 저장된 선택 데이터 > 빈 배열
        const dataToUse = payload.sourceData || selectedData;
        const periodToUse = payload.period || getDefaultPeriod();

        console.log("[useScheduleGenerator] 사용할 sourceData:", dataToUse.length, "건");
        console.log("[useScheduleGenerator] 사용할 period:", periodToUse);

        currentRequestIdRef.current = payload.requestId;
        currentConfigRef.current = configToUse;
        setIsLoading(true);
        toast.loading("스케줄 생성 중...", { id: "schedule-generate" });

        try {
          // 미리보기 API 호출
          const response = await apiClient.post("/schedule/preview", {
            config: configToUse,
            scheduleType: payload.scheduleType,
            sourceData: dataToUse,
            period: periodToUse,
          });

          console.log("[useScheduleGenerator] 미리보기 응답:", response.data);

          if (!response.data.success) {
            toast.error(response.data.message || "미리보기 생성 실패", { id: "schedule-generate" });
            v2EventBus.emit(V2_EVENTS.SCHEDULE_GENERATE_ERROR, {
              requestId: payload.requestId,
              error: response.data.message || "미리보기 생성 실패",
              scheduleType: payload.scheduleType,
            });
            return;
          }

          setPreviewResult(response.data.preview);
          setShowConfirmDialog(true);
          toast.success("스케줄 미리보기가 생성되었습니다.", { id: "schedule-generate" });

          // 미리보기 결과 이벤트 발송 (다른 컴포넌트가 필요할 수 있음)
          v2EventBus.emit(V2_EVENTS.SCHEDULE_GENERATE_PREVIEW, {
            requestId: payload.requestId,
            scheduleType: payload.scheduleType,
            preview: response.data.preview,
          });
        } catch (error: any) {
          console.error("[ScheduleGeneratorService] 미리보기 오류:", error);
          toast.dismiss("schedule-generate");
          showErrorToast("스케줄 미리보기 생성에 실패했습니다", error, { guidance: "스케줄 설정을 확인하고 다시 시도해 주세요." });
          v2EventBus.emit(V2_EVENTS.SCHEDULE_GENERATE_ERROR, {
            requestId: payload.requestId,
            error: error.message,
            scheduleType: payload.scheduleType,
          });
        } finally {
          setIsLoading(false);
        }
      },
    );
    return unsubscribe;
  }, [selectedData, scheduleConfig]);

  // 3. 스케줄 적용 처리 (SCHEDULE_GENERATE_APPLY 수신)
  useEffect(() => {
    const unsubscribe = v2EventBus.subscribe(
      V2_EVENTS.SCHEDULE_GENERATE_APPLY,
      async (payload: V2ScheduleGenerateApplyEvent) => {
        if (payload.requestId !== currentRequestIdRef.current) return;

        if (!payload.confirmed) {
          setShowConfirmDialog(false);
          return;
        }

        // 저장된 config 또는 기존 scheduleConfig 사용
        const configToUse = currentConfigRef.current || scheduleConfig;

        setIsLoading(true);
        toast.loading("스케줄 적용 중...", { id: "schedule-apply" });

        try {
          const response = await apiClient.post("/schedule/apply", {
            config: configToUse,
            preview: previewResult,
            options: { deleteExisting: true, updateMode: "replace" },
          });

          if (!response.data.success) {
            toast.error(response.data.message || "스케줄 적용 실패", { id: "schedule-apply" });
            return;
          }

          // 완료 이벤트 발송
          v2EventBus.emit(V2_EVENTS.SCHEDULE_GENERATE_COMPLETE, {
            requestId: payload.requestId,
            success: true,
            applied: response.data.applied,
            scheduleType: configToUse?.scheduleType || "PRODUCTION",
            targetTableName: configToUse?.target?.tableName || "schedule_mng",
          });

          // 테이블 새로고침 이벤트 발송
          v2EventBus.emit(V2_EVENTS.TABLE_REFRESH, {
            tableName: configToUse?.target?.tableName || "schedule_mng",
          });

          toast.success(`${response.data.applied?.created || 0}건의 스케줄이 생성되었습니다.`, {
            id: "schedule-apply",
          });
          setShowConfirmDialog(false);
          setPreviewResult(null);
        } catch (error: any) {
          console.error("[ScheduleGeneratorService] 적용 오류:", error);
          toast.dismiss("schedule-apply");
          showErrorToast("스케줄 적용에 실패했습니다", error, { guidance: "스케줄 설정과 데이터를 확인하고 다시 시도해 주세요." });
        } finally {
          setIsLoading(false);
        }
      },
    );
    return unsubscribe;
  }, [previewResult, scheduleConfig]);

  // 확인 다이얼로그 핸들러
  const handleConfirm = useCallback((confirmed: boolean) => {
    v2EventBus.emit(V2_EVENTS.SCHEDULE_GENERATE_APPLY, {
      requestId: currentRequestIdRef.current,
      confirmed,
    });
  }, []);

  // 다이얼로그 닫기
  const closeDialog = useCallback(() => {
    setShowConfirmDialog(false);
    setPreviewResult(null);
  }, []);

  return {
    isLoading,
    showConfirmDialog,
    previewResult,
    handleConfirm,
    closeDialog,
  };
}

// ============================================================================
// 스케줄 확인 다이얼로그 컴포넌트
// ============================================================================

export { ScheduleConfirmDialog } from "./ScheduleConfirmDialog";
