"use client";

import React, { createContext, useContext, useCallback, useRef, useState } from "react";
import { logger } from "@/lib/utils/logger";

/**
 * 분할 패널 내 화면 위치
 */
export type SplitPanelPosition = "left" | "right";

/**
 * 데이터 수신자 인터페이스
 */
export interface SplitPanelDataReceiver {
  componentId: string;
  componentType: string;
  receiveData: (data: any[], mode: "append" | "replace" | "merge") => Promise<void>;
}

/**
 * 부모 데이터 매핑 설정
 * 좌측 화면에서 선택한 데이터를 우측 화면 저장 시 자동으로 포함
 */
export interface ParentDataMapping {
  sourceColumn: string;  // 좌측 화면의 컬럼명 (예: equipment_code)
  targetColumn: string;  // 우측 화면 저장 시 사용할 컬럼명 (예: equipment_code)
}

/**
 * 연결 필터 설정
 * 좌측 화면에서 선택한 데이터로 우측 화면의 테이블을 자동 필터링
 */
export interface LinkedFilter {
  sourceColumn: string;  // 좌측 화면의 컬럼명 (예: equipment_code)
  targetColumn: string;  // 우측 화면 필터링에 사용할 컬럼명 (예: equipment_code)
}

/**
 * 분할 패널 컨텍스트 값
 */
interface SplitPanelContextValue {
  // 분할 패널 ID
  splitPanelId: string;
  
  // 좌측/우측 화면 ID
  leftScreenId: number | null;
  rightScreenId: number | null;
  
  // 데이터 수신자 등록/해제
  registerReceiver: (position: SplitPanelPosition, componentId: string, receiver: SplitPanelDataReceiver) => void;
  unregisterReceiver: (position: SplitPanelPosition, componentId: string) => void;
  
  // 반대편 화면으로 데이터 전달
  transferToOtherSide: (
    fromPosition: SplitPanelPosition,
    data: any[],
    targetComponentId?: string, // 특정 컴포넌트 지정 (없으면 첫 번째 수신자)
    mode?: "append" | "replace" | "merge"
  ) => Promise<{ success: boolean; message: string }>;
  
  // 반대편 화면의 수신자 목록 가져오기
  getOtherSideReceivers: (fromPosition: SplitPanelPosition) => SplitPanelDataReceiver[];
  
  // 현재 위치 확인
  isInSplitPanel: boolean;
  
  // screenId로 위치 찾기
  getPositionByScreenId: (screenId: number) => SplitPanelPosition | null;
  
  // 🆕 우측에 추가된 항목 ID 관리 (좌측 테이블에서 필터링용)
  addedItemIds: Set<string>;
  addItemIds: (ids: string[]) => void;
  removeItemIds: (ids: string[]) => void;
  clearItemIds: () => void;
  
  // 🆕 좌측 선택 데이터 관리 (우측 화면 저장 시 부모 키 전달용)
  selectedLeftData: Record<string, any> | null;
  setSelectedLeftData: (data: Record<string, any> | null) => void;
  
  // 🆕 부모 데이터 매핑 설정
  parentDataMapping: ParentDataMapping[];
  
  // 🆕 매핑된 부모 데이터 가져오기 (우측 화면 저장 시 사용)
  getMappedParentData: () => Record<string, any>;
  
  // 🆕 연결 필터 설정 (좌측 선택 → 우측 테이블 필터링)
  linkedFilters: LinkedFilter[];
  
  // 🆕 연결 필터 값 가져오기 (우측 테이블 조회 시 사용)
  getLinkedFilterValues: () => Record<string, any>;
}

const SplitPanelContext = createContext<SplitPanelContextValue | null>(null);

interface SplitPanelProviderProps {
  splitPanelId: string;
  leftScreenId: number | null;
  rightScreenId: number | null;
  parentDataMapping?: ParentDataMapping[];  // 🆕 부모 데이터 매핑 설정
  linkedFilters?: LinkedFilter[];  // 🆕 연결 필터 설정
  children: React.ReactNode;
}

/**
 * 분할 패널 컨텍스트 프로바이더
 */
export function SplitPanelProvider({
  splitPanelId,
  leftScreenId,
  rightScreenId,
  parentDataMapping = [],
  linkedFilters = [],
  children,
}: SplitPanelProviderProps) {
  // 좌측/우측 화면의 데이터 수신자 맵
  const leftReceiversRef = useRef<Map<string, SplitPanelDataReceiver>>(new Map());
  const rightReceiversRef = useRef<Map<string, SplitPanelDataReceiver>>(new Map());
  
  // 강제 리렌더링용 상태
  const [, forceUpdate] = useState(0);
  
  // 🆕 우측에 추가된 항목 ID 상태
  const [addedItemIds, setAddedItemIds] = useState<Set<string>>(new Set());
  
  // 🆕 좌측에서 선택된 데이터 상태
  const [selectedLeftData, setSelectedLeftData] = useState<Record<string, any> | null>(null);

  /**
   * 데이터 수신자 등록
   */
  const registerReceiver = useCallback(
    (position: SplitPanelPosition, componentId: string, receiver: SplitPanelDataReceiver) => {
      const receiversRef = position === "left" ? leftReceiversRef : rightReceiversRef;
      receiversRef.current.set(componentId, receiver);
      
      logger.debug(`[SplitPanelContext] 수신자 등록: ${position} - ${componentId}`, {
        componentType: receiver.componentType,
      });
      
      forceUpdate((n) => n + 1);
    },
    []
  );

  /**
   * 데이터 수신자 해제
   */
  const unregisterReceiver = useCallback(
    (position: SplitPanelPosition, componentId: string) => {
      const receiversRef = position === "left" ? leftReceiversRef : rightReceiversRef;
      receiversRef.current.delete(componentId);
      
      logger.debug(`[SplitPanelContext] 수신자 해제: ${position} - ${componentId}`);
      
      forceUpdate((n) => n + 1);
    },
    []
  );

  /**
   * 반대편 화면의 수신자 목록 가져오기
   */
  const getOtherSideReceivers = useCallback(
    (fromPosition: SplitPanelPosition): SplitPanelDataReceiver[] => {
      const receiversRef = fromPosition === "left" ? rightReceiversRef : leftReceiversRef;
      return Array.from(receiversRef.current.values());
    },
    []
  );

  /**
   * 반대편 화면으로 데이터 전달
   */
  const transferToOtherSide = useCallback(
    async (
      fromPosition: SplitPanelPosition,
      data: any[],
      targetComponentId?: string,
      mode: "append" | "replace" | "merge" = "append"
    ): Promise<{ success: boolean; message: string }> => {
      const toPosition = fromPosition === "left" ? "right" : "left";
      const receiversRef = fromPosition === "left" ? rightReceiversRef : leftReceiversRef;
      
      logger.info(`[SplitPanelContext] 데이터 전달 시작: ${fromPosition} → ${toPosition}`, {
        dataCount: data.length,
        targetComponentId,
        mode,
        availableReceivers: Array.from(receiversRef.current.keys()),
      });

      if (receiversRef.current.size === 0) {
        const message = `${toPosition === "left" ? "좌측" : "우측"} 화면에 데이터를 받을 수 있는 컴포넌트가 없습니다.`;
        logger.warn(`[SplitPanelContext] ${message}`);
        return { success: false, message };
      }

      try {
        let targetReceiver: SplitPanelDataReceiver | undefined;

        if (targetComponentId) {
          // 특정 컴포넌트 지정
          targetReceiver = receiversRef.current.get(targetComponentId);
          if (!targetReceiver) {
            const message = `타겟 컴포넌트 '${targetComponentId}'를 찾을 수 없습니다.`;
            logger.warn(`[SplitPanelContext] ${message}`);
            return { success: false, message };
          }
        } else {
          // 첫 번째 수신자 사용
          targetReceiver = receiversRef.current.values().next().value;
        }

        if (!targetReceiver) {
          return { success: false, message: "데이터 수신자를 찾을 수 없습니다." };
        }

        await targetReceiver.receiveData(data, mode);
        
        const message = `${data.length}개 항목이 ${toPosition === "left" ? "좌측" : "우측"} 화면으로 전달되었습니다.`;
        logger.info(`[SplitPanelContext] ${message}`);
        
        return { success: true, message };
      } catch (error: any) {
        const message = error.message || "데이터 전달 중 오류가 발생했습니다.";
        logger.error(`[SplitPanelContext] 데이터 전달 실패`, error);
        return { success: false, message };
      }
    },
    []
  );

  /**
   * screenId로 위치 찾기
   */
  const getPositionByScreenId = useCallback(
    (screenId: number): SplitPanelPosition | null => {
      if (leftScreenId === screenId) return "left";
      if (rightScreenId === screenId) return "right";
      return null;
    },
    [leftScreenId, rightScreenId]
  );

  /**
   * 🆕 추가된 항목 ID 등록
   */
  const addItemIds = useCallback((ids: string[]) => {
    setAddedItemIds((prev) => {
      const newSet = new Set(prev);
      ids.forEach((id) => newSet.add(id));
      logger.debug(`[SplitPanelContext] 항목 ID 추가: ${ids.length}개`, { ids });
      return newSet;
    });
  }, []);

  /**
   * 🆕 추가된 항목 ID 제거
   */
  const removeItemIds = useCallback((ids: string[]) => {
    setAddedItemIds((prev) => {
      const newSet = new Set(prev);
      ids.forEach((id) => newSet.delete(id));
      logger.debug(`[SplitPanelContext] 항목 ID 제거: ${ids.length}개`, { ids });
      return newSet;
    });
  }, []);

  /**
   * 🆕 모든 항목 ID 초기화
   */
  const clearItemIds = useCallback(() => {
    setAddedItemIds(new Set());
    logger.debug(`[SplitPanelContext] 항목 ID 초기화`);
  }, []);

  /**
   * 🆕 좌측 선택 데이터 설정
   */
  const handleSetSelectedLeftData = useCallback((data: Record<string, any> | null) => {
    logger.info(`[SplitPanelContext] 좌측 선택 데이터 설정:`, {
      hasData: !!data,
      dataKeys: data ? Object.keys(data) : [],
    });
    setSelectedLeftData(data);
  }, []);

  /**
   * 🆕 매핑된 부모 데이터 가져오기
   * 우측 화면에서 저장 시 이 함수를 호출하여 부모 키 값을 가져옴
   * 
   * 동작 방식:
   * 1. 좌측 데이터의 모든 컬럼을 자동으로 전달 (동일한 컬럼명이면 자동 매핑)
   * 2. 명시적 매핑이 있으면 소스→타겟 변환 적용 (다른 컬럼명으로 매핑 시)
   */
  const getMappedParentData = useCallback((): Record<string, any> => {
    if (!selectedLeftData) {
      return {};
    }

    const mappedData: Record<string, any> = {};
    
    // 1단계: 좌측 데이터의 모든 컬럼을 자동으로 전달 (동일 컬럼명 자동 매핑)
    for (const [key, value] of Object.entries(selectedLeftData)) {
      if (value !== undefined && value !== null) {
        mappedData[key] = value;
      }
    }
    
    // 2단계: 명시적 매핑이 있으면 추가 적용 (다른 컬럼명으로 변환)
    for (const mapping of parentDataMapping) {
      const value = selectedLeftData[mapping.sourceColumn];
      if (value !== undefined && value !== null) {
        // 소스와 타겟이 다른 경우에만 추가 매핑
        if (mapping.sourceColumn !== mapping.targetColumn) {
          mappedData[mapping.targetColumn] = value;
          logger.debug(`[SplitPanelContext] 명시적 매핑: ${mapping.sourceColumn} → ${mapping.targetColumn} = ${value}`);
        }
      }
    }

    logger.info(`[SplitPanelContext] 매핑된 부모 데이터 (자동+명시적):`, {
      autoMappedKeys: Object.keys(selectedLeftData),
      explicitMappings: parentDataMapping.length,
      finalKeys: Object.keys(mappedData),
    });
    return mappedData;
  }, [selectedLeftData, parentDataMapping]);

  /**
   * 🆕 연결 필터 값 가져오기
   * 우측 화면의 테이블 조회 시 이 값으로 필터링
   */
  const getLinkedFilterValues = useCallback((): Record<string, any> => {
    if (!selectedLeftData || linkedFilters.length === 0) {
      return {};
    }

    const filterValues: Record<string, any> = {};
    
    for (const filter of linkedFilters) {
      const value = selectedLeftData[filter.sourceColumn];
      if (value !== undefined && value !== null && value !== "") {
        filterValues[filter.targetColumn] = value;
        logger.debug(`[SplitPanelContext] 연결 필터: ${filter.sourceColumn} → ${filter.targetColumn} = ${value}`);
      }
    }

    logger.info(`[SplitPanelContext] 연결 필터 값:`, filterValues);
    return filterValues;
  }, [selectedLeftData, linkedFilters]);

  // 🆕 useMemo로 value 객체 메모이제이션 (무한 루프 방지)
  const value = React.useMemo<SplitPanelContextValue>(() => ({
    splitPanelId,
    leftScreenId,
    rightScreenId,
    registerReceiver,
    unregisterReceiver,
    transferToOtherSide,
    getOtherSideReceivers,
    isInSplitPanel: true,
    getPositionByScreenId,
    addedItemIds,
    addItemIds,
    removeItemIds,
    clearItemIds,
    // 🆕 좌측 선택 데이터 관련
    selectedLeftData,
    setSelectedLeftData: handleSetSelectedLeftData,
    parentDataMapping,
    getMappedParentData,
    // 🆕 연결 필터 관련
    linkedFilters,
    getLinkedFilterValues,
  }), [
    splitPanelId,
    leftScreenId,
    rightScreenId,
    registerReceiver,
    unregisterReceiver,
    transferToOtherSide,
    getOtherSideReceivers,
    getPositionByScreenId,
    addedItemIds,
    addItemIds,
    removeItemIds,
    clearItemIds,
    selectedLeftData,
    handleSetSelectedLeftData,
    parentDataMapping,
    getMappedParentData,
    linkedFilters,
    getLinkedFilterValues,
  ]);

  return (
    <SplitPanelContext.Provider value={value}>
      {children}
    </SplitPanelContext.Provider>
  );
}

/**
 * 분할 패널 컨텍스트 훅
 */
export function useSplitPanelContext() {
  return useContext(SplitPanelContext);
}

/**
 * 분할 패널 내부인지 확인하는 훅
 */
export function useIsInSplitPanel(): boolean {
  const context = useContext(SplitPanelContext);
  return context?.isInSplitPanel ?? false;
}

