"use client";

/**
 * 화면 간 데이터 전달 훅
 * 
 * 화면 간, 컴포넌트 간 데이터 전달을 통합된 방식으로 처리합니다.
 * 
 * 사용 시나리오:
 * 1. 마스터-디테일 패턴: 목록에서 선택 → 상세 화면에 데이터 전달
 * 2. 모달 오픈: 버튼 클릭 → 모달에 선택된 데이터 전달
 * 3. 화면 임베딩: 부모 화면 → 자식 화면에 필터 조건 전달
 */

import { useCallback, useEffect, useRef } from "react";
import type {
  ScreenDataTransferConfig,
  FieldMapping,
  DataTransferTrigger,
} from "@/types/v2-form";

// ===== 이벤트 이름 상수 =====
export const SCREEN_DATA_TRANSFER_EVENT = "screenDataTransfer";

// ===== 전역 데이터 스토어 (간단한 인메모리 저장소) =====
const dataStore = new Map<string, unknown>();

/**
 * 데이터 스토어에 데이터 저장
 */
export function setTransferData(key: string, data: unknown): void {
  dataStore.set(key, data);
}

/**
 * 데이터 스토어에서 데이터 조회
 */
export function getTransferData<T = unknown>(key: string): T | undefined {
  return dataStore.get(key) as T | undefined;
}

/**
 * 데이터 스토어에서 데이터 삭제
 */
export function clearTransferData(key: string): void {
  dataStore.delete(key);
}

// ===== 데이터 변환 유틸 =====

/**
 * 필드 매핑 적용
 */
export function applyFieldMappings(
  data: Record<string, unknown>,
  mappings: FieldMapping[]
): Record<string, unknown> {
  const result: Record<string, unknown> = {};
  
  for (const mapping of mappings) {
    const sourceValue = data[mapping.sourceField];
    
    // 변환 적용
    let targetValue = sourceValue;
    
    switch (mapping.transform) {
      case "copy":
        // 그대로 복사
        targetValue = sourceValue;
        break;
        
      case "lookup":
        // TODO: 다른 테이블에서 조회
        targetValue = sourceValue;
        break;
        
      case "calculate":
        // TODO: 계산식 적용
        targetValue = sourceValue;
        break;
        
      case "format":
        // TODO: 포맷팅 적용
        if (typeof sourceValue === "string" && mapping.transformConfig?.format) {
          // 간단한 포맷 적용 (확장 가능)
          targetValue = sourceValue;
        }
        break;
        
      default:
        targetValue = sourceValue;
    }
    
    result[mapping.targetField] = targetValue;
  }
  
  return result;
}

// ===== 훅 =====

interface UseScreenDataTransferOptions {
  // 이 컴포넌트/화면의 ID
  screenId?: number;
  componentId?: string;
  
  // 데이터 수신 시 콜백
  onReceiveData?: (data: Record<string, unknown>, trigger: DataTransferTrigger) => void;
  
  // 자동 구독할 소스 (다른 화면에서 이 화면으로 전달되는 데이터)
  subscribeFrom?: {
    sourceScreenId?: number;
    sourceComponentId?: string;
  };
}

interface UseScreenDataTransferReturn {
  /**
   * 데이터 전송
   */
  sendData: (
    data: Record<string, unknown>,
    config: {
      targetScreenId?: number;
      targetComponentId?: string;
      mappings?: FieldMapping[];
      trigger?: DataTransferTrigger;
    }
  ) => void;
  
  /**
   * 데이터 수신 대기 (수동)
   */
  receiveData: () => Record<string, unknown> | undefined;
  
  /**
   * 스토어에서 데이터 조회 (키 기반)
   */
  getStoredData: <T = unknown>(key: string) => T | undefined;
  
  /**
   * 스토어에 데이터 저장 (키 기반)
   */
  setStoredData: (key: string, data: unknown) => void;
}

/**
 * 화면 간 데이터 전달 훅
 */
export function useScreenDataTransfer(
  options: UseScreenDataTransferOptions = {}
): UseScreenDataTransferReturn {
  const { screenId, componentId, onReceiveData, subscribeFrom } = options;
  
  const receiveCallbackRef = useRef(onReceiveData);
  receiveCallbackRef.current = onReceiveData;
  
  // 이벤트 리스너 등록 (데이터 수신)
  useEffect(() => {
    if (!subscribeFrom && !screenId && !componentId) return;
    
    const handleDataTransfer = (event: Event) => {
      const customEvent = event as CustomEvent<{
        sourceScreenId?: number;
        sourceComponentId?: string;
        targetScreenId?: number;
        targetComponentId?: string;
        data: Record<string, unknown>;
        trigger: DataTransferTrigger;
      }>;
      
      const detail = customEvent.detail;
      
      // 이 화면/컴포넌트를 대상으로 하는지 확인
      const isTargetMatch = 
        (detail.targetScreenId && detail.targetScreenId === screenId) ||
        (detail.targetComponentId && detail.targetComponentId === componentId);
      
      // 구독 중인 소스에서 온 데이터인지 확인
      const isSourceMatch = subscribeFrom && (
        (subscribeFrom.sourceScreenId && subscribeFrom.sourceScreenId === detail.sourceScreenId) ||
        (subscribeFrom.sourceComponentId && subscribeFrom.sourceComponentId === detail.sourceComponentId)
      );
      
      if (isTargetMatch || isSourceMatch) {
        receiveCallbackRef.current?.(detail.data, detail.trigger);
      }
    };
    
    window.addEventListener(SCREEN_DATA_TRANSFER_EVENT, handleDataTransfer);
    
    return () => {
      window.removeEventListener(SCREEN_DATA_TRANSFER_EVENT, handleDataTransfer);
    };
  }, [screenId, componentId, subscribeFrom]);
  
  /**
   * 데이터 전송
   */
  const sendData = useCallback((
    data: Record<string, unknown>,
    config: {
      targetScreenId?: number;
      targetComponentId?: string;
      mappings?: FieldMapping[];
      trigger?: DataTransferTrigger;
    }
  ) => {
    // 매핑 적용
    const mappedData = config.mappings 
      ? applyFieldMappings(data, config.mappings)
      : data;
    
    // 이벤트 발생
    if (typeof window !== "undefined") {
      window.dispatchEvent(new CustomEvent(SCREEN_DATA_TRANSFER_EVENT, {
        detail: {
          sourceScreenId: screenId,
          sourceComponentId: componentId,
          targetScreenId: config.targetScreenId,
          targetComponentId: config.targetComponentId,
          data: mappedData,
          trigger: config.trigger || "manual",
        }
      }));
    }
    
    // 스토어에도 저장 (비동기 조회용)
    const storeKey = config.targetScreenId 
      ? `screen_${config.targetScreenId}` 
      : config.targetComponentId 
        ? `component_${config.targetComponentId}`
        : "default";
    setTransferData(storeKey, mappedData);
  }, [screenId, componentId]);
  
  /**
   * 데이터 수신 (스토어에서 조회)
   */
  const receiveData = useCallback(() => {
    const storeKey = screenId 
      ? `screen_${screenId}` 
      : componentId 
        ? `component_${componentId}`
        : "default";
    return getTransferData<Record<string, unknown>>(storeKey);
  }, [screenId, componentId]);
  
  return {
    sendData,
    receiveData,
    getStoredData: getTransferData,
    setStoredData: setTransferData,
  };
}

/**
 * 간편한 데이터 전달 훅 (설정 기반)
 */
export function useConfiguredDataTransfer(config: ScreenDataTransferConfig) {
  const { source, target, trigger, condition } = config;
  
  const { sendData } = useScreenDataTransfer({
    screenId: source.screenId,
    componentId: source.componentId,
  });
  
  /**
   * 설정된 대로 데이터 전달
   */
  const transfer = useCallback((data: Record<string, unknown>) => {
    // 조건 체크
    if (condition) {
      const fieldValue = data[condition.field];
      let conditionMet = false;
      
      switch (condition.operator) {
        case "=":
          conditionMet = fieldValue === condition.value;
          break;
        case "!=":
          conditionMet = fieldValue !== condition.value;
          break;
        case ">":
          conditionMet = Number(fieldValue) > Number(condition.value);
          break;
        case "<":
          conditionMet = Number(fieldValue) < Number(condition.value);
          break;
        case "in":
          conditionMet = Array.isArray(condition.value) && condition.value.includes(fieldValue);
          break;
        case "notIn":
          conditionMet = Array.isArray(condition.value) && !condition.value.includes(fieldValue);
          break;
      }
      
      if (!conditionMet) {
        return; // 조건 불충족 시 전달 안 함
      }
    }
    
    // 소스 필드만 추출
    const sourceData: Record<string, unknown> = {};
    for (const field of source.fields) {
      sourceData[field] = data[field];
    }
    
    // 전달
    sendData(sourceData, {
      targetScreenId: target.screenId,
      mappings: target.mappings,
      trigger,
    });
  }, [source.fields, target.screenId, target.mappings, trigger, condition, sendData]);
  
  return { transfer };
}

export default useScreenDataTransfer;

