"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { apiClient } from "@/lib/api/client";
import { dataApi } from "@/lib/api/data";
import {
	normalizeWorkOrderProcess,
	type WorkOrderProcessRaw,
	type WorkOrderProcessView,
} from "./types";

/* ------------------------------------------------------------------ */
/* Types (WorkOrderList.tsx와 동일 스키마)                              */
/* ------------------------------------------------------------------ */

export interface WorkInstruction {
	id: string;
	work_instruction_no: string;
	item_id: string;
	item_name: string;
	item_code: string;
	item_number: string;
	qty: number;
	completed_qty: number;
	status: string;
	progress_status: string;
	routing: string | null;
	start_date: string;
	end_date: string;
	equipment_id: string;
	work_team: string;
	worker: string;
}

/** Phase D: 정규화 View re-export (기존 타입명 유지 호환) */
export type WorkOrderProcess = WorkOrderProcessView;

export interface ProcessMng {
	id: string;
	process_code: string;
	process_name: string;
}

export interface EquipmentMng {
	id: string;
	equipment_code: string;
	equipment_name: string;
}

const REFRESH_COOLDOWN_MS = 3000;

/**
 * 공정실행 화면 데이터 훅
 *
 * - 진입 시 1회 sync-work-instructions POST + 데이터 로드
 * - refresh(): 수동 새로고침 — sync 포함, 3초 쿨다운 (연타 차단)
 * - refetch(): mutation 이후 — sync 없이 데이터만 재조회
 * - 에러 → sonner toast (silent catch 금지)
 */
export function useProcessData() {
	const [instructions, setInstructions] = useState<WorkInstruction[]>([]);
	const [allProcesses, setAllProcesses] = useState<WorkOrderProcess[]>([]);
	const [processList, setProcessList] = useState<ProcessMng[]>([]);
	const [equipmentList, setEquipmentList] = useState<EquipmentMng[]>([]);
	const [itemNameMap, setItemNameMap] = useState<Record<string, string>>({});
	const [itemTypeMap, setItemTypeMap] = useState<Record<string, string>>({});
	const [loading, setLoading] = useState(true);
	const [syncing, setSyncing] = useState(false);

	const lastRefreshAt = useRef<number>(0);
	const inFlight = useRef<Promise<void> | null>(null);

	const fetchData = useCallback(
		async (opts?: { withSync?: boolean }): Promise<void> => {
			// 동시 호출 방지 (같은 fetch가 이미 진행 중이면 그 Promise를 공유)
			if (inFlight.current) return inFlight.current;

			const task = (async () => {
				setLoading(true);
				if (opts?.withSync) setSyncing(true);
				try {
					if (opts?.withSync) {
						try {
							await apiClient.post("/pop/production/sync-work-instructions");
						} catch {
							toast.warning(
								"동기화 실패 — 최신 작업지시가 반영되지 않을 수 있습니다",
							);
						}
					}

					const [wiRes, procRes, pmRes, eqRes] = await Promise.all([
						apiClient.get("/work-instruction/list"),
						apiClient.get("/pop/production/processes"),
						dataApi.getTableData("process_mng", { size: 500 }),
						dataApi.getTableData("equipment_mng", { size: 500 }),
					]);

					// work-instruction: header+detail 조인이라 id 중복 → 첫 행만 취함
					let wiRaw: Record<string, unknown>[] = [];
					if (wiRes.data?.data) {
						wiRaw = Array.isArray(wiRes.data.data)
							? wiRes.data.data
							: wiRes.data.data.rows || [];
					} else if (Array.isArray(wiRes.data)) {
						wiRaw = wiRes.data;
					}
					const seen = new Set<string>();
					const wiData: WorkInstruction[] = [];
					const newItemNameMap: Record<string, string> = {};
					const newItemTypeMap: Record<string, string> = {};
					for (const raw of wiRaw) {
						const wiId = String(raw.wi_id || raw.id || "");
						const rawItemNumber = String(raw.item_number || "");
						const rawItemName = String(raw.item_name || "");
						const rawItemType = String(raw.item_type || "");
						if (rawItemNumber && rawItemName) {
							newItemNameMap[rawItemNumber] = rawItemName;
						}
						if (rawItemNumber && rawItemType) {
							newItemTypeMap[rawItemNumber] = rawItemType;
						}
						if (!wiId || seen.has(wiId)) continue;
						seen.add(wiId);
						wiData.push({
							...raw,
							id: wiId,
							item_name: rawItemName,
							item_code: String(raw.item_code || ""),
							item_number: rawItemNumber,
							qty: parseInt(String(raw.total_qty || raw.qty || 0), 10),
						} as unknown as WorkInstruction);
					}
					setInstructions(wiData);
					setItemNameMap(newItemNameMap);
					setItemTypeMap(newItemTypeMap);
					const rawRows: WorkOrderProcessRaw[] = procRes.data?.data ?? [];
					// 마스터(wop) + accepted_results 평탄화: 신 구조 접수 카드 = wop_result 항목을
					// 기존 UI 의 "분할 카드(parent_process_id 있음)" 형태로 펼쳐서 기존 필터 로직과
					// 호환 유지. virtual row 의 id = wop_result.id (라우팅/API body 식별자)
					const flat: WorkOrderProcessView[] = [];
					for (const raw of rawRows) {
						const master = normalizeWorkOrderProcess(raw);
						flat.push(master);
						for (const ar of master.accepted_results) {
							flat.push({
								...master,
								// 접수 카드 → virtual split row
								id: ar.id, // wop_result.id
								parent_process_id: master.id, // 마스터(wop.id) 참조
								status: ar.status,
								result_status: ar.result_status,
								input_qty: ar.input_qty,
								good_qty: ar.good_qty,
								defect_qty: ar.defect_qty,
								concession_qty: ar.concession_qty,
								total_production_qty: ar.total_production_qty,
								is_rework: ar.is_rework,
								rework_source_id: ar.rework_source_id,
								accepted_by: ar.accepted_by,
								accepted_at: ar.accepted_at,
								started_at: ar.started_at,
								completed_at: ar.completed_at,
								equipment_code: ar.equipment_code,
								batch_id: ar.batch_id ?? master.batch_id,
								// split 표시용 (접수 #n)
								split_no: ar.seq,
								split_total: master.accepted_results.length,
								// 분할 카드 자체의 accepted_results 는 의미 없음 (재귀 금지)
								accepted_results: [],
							});
						}
					}
					setAllProcesses(flat);
					setProcessList((pmRes.data ?? []) as ProcessMng[]);
					setEquipmentList((eqRes.data ?? []) as EquipmentMng[]);
				} catch {
					toast.error("데이터 조회 실패");
				} finally {
					setLoading(false);
					setSyncing(false);
				}
			})();

			inFlight.current = task;
			try {
				await task;
			} finally {
				inFlight.current = null;
			}
		},
		[],
	);

	// 진입 시 1회만 sync + 로드
	useEffect(() => {
		fetchData({ withSync: true });
		// fetchData는 stable — 의존성에 넣으면 useCallback deps 변화 없어도 무관하나,
		// 명시적으로 빈 배열로 두어 "마운트 시 정확히 1회"를 강제
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, []);

	/** 수동 새로고침 — sync 포함, 3초 쿨다운 */
	const refresh = useCallback(() => {
		const now = Date.now();
		if (now - lastRefreshAt.current < REFRESH_COOLDOWN_MS) return;
		lastRefreshAt.current = now;
		fetchData({ withSync: true });
	}, [fetchData]);

	/** Mutation(접수/실적/취소) 직후 — sync 없이 데이터만 재조회 */
	const refetch = useCallback(() => {
		fetchData({ withSync: false });
	}, [fetchData]);

	return {
		instructions,
		allProcesses,
		processList,
		equipmentList,
		itemNameMap,
		itemTypeMap,
		loading,
		syncing,
		refresh,
		refetch,
	};
}
