"use client";

/**
 * 계층구조 코드 선택 컴포넌트 (1단계, 2단계, 3단계 셀렉트박스)
 * 
 * @example
 * // 기본 사용
 * <HierarchicalCodeSelect
 *   categoryCode="PRODUCT_CATEGORY"
 *   maxDepth={3}
 *   value={selectedCode}
 *   onChange={(code) => setSelectedCode(code)}
 * />
 * 
 * @example
 * // 특정 depth까지만 선택
 * <HierarchicalCodeSelect
 *   categoryCode="LOCATION"
 *   maxDepth={2}
 *   value={selectedCode}
 *   onChange={(code) => setSelectedCode(code)}
 * />
 */

import React, { useState, useEffect, useCallback, useMemo } from "react";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Label } from "@/components/ui/label";
import { commonCodeApi } from "@/lib/api/commonCode";
import { Loader2 } from "lucide-react";
import type { CodeInfo } from "@/types/commonCode";

export interface HierarchicalCodeSelectProps {
  /** 코드 카테고리 */
  categoryCode: string;
  
  /** 최대 깊이 (1, 2, 3) */
  maxDepth?: 1 | 2 | 3;
  
  /** 현재 선택된 값 (최종 선택된 코드값) */
  value?: string;
  
  /** 값 변경 핸들러 */
  onChange?: (codeValue: string, codeInfo?: CodeInfo, fullPath?: CodeInfo[]) => void;
  
  /** 각 단계별 라벨 */
  labels?: [string, string?, string?];
  
  /** 각 단계별 placeholder */
  placeholders?: [string, string?, string?];
  
  /** 비활성화 */
  disabled?: boolean;
  
  /** 필수 입력 */
  required?: boolean;
  
  /** 메뉴 OBJID (메뉴 기반 필터링) */
  menuObjid?: number;
  
  /** 추가 클래스 */
  className?: string;
  
  /** 인라인 표시 (가로 배열) */
  inline?: boolean;
}

interface LoadingState {
  level1: boolean;
  level2: boolean;
  level3: boolean;
}

export function HierarchicalCodeSelect({
  categoryCode,
  maxDepth = 3,
  value,
  onChange,
  labels = ["1단계", "2단계", "3단계"],
  placeholders = ["선택하세요", "선택하세요", "선택하세요"],
  disabled = false,
  required = false,
  menuObjid,
  className = "",
  inline = false,
}: HierarchicalCodeSelectProps) {
  // 각 단계별 옵션
  const [level1Options, setLevel1Options] = useState<CodeInfo[]>([]);
  const [level2Options, setLevel2Options] = useState<CodeInfo[]>([]);
  const [level3Options, setLevel3Options] = useState<CodeInfo[]>([]);
  
  // 각 단계별 선택값
  const [selectedLevel1, setSelectedLevel1] = useState<string>("");
  const [selectedLevel2, setSelectedLevel2] = useState<string>("");
  const [selectedLevel3, setSelectedLevel3] = useState<string>("");
  
  // 로딩 상태
  const [loading, setLoading] = useState<LoadingState>({
    level1: false,
    level2: false,
    level3: false,
  });
  
  // 모든 코드 데이터 (경로 추적용)
  const [allCodes, setAllCodes] = useState<CodeInfo[]>([]);

  // 1단계 코드 로드 (최상위)
  const loadLevel1Codes = useCallback(async () => {
    if (!categoryCode) return;
    
    setLoading(prev => ({ ...prev, level1: true }));
    try {
      const response = await commonCodeApi.hierarchy.getHierarchicalCodes(
        categoryCode,
        null, // 부모 없음 (최상위)
        1,    // depth = 1
        menuObjid
      );
      
      if (response.success && response.data) {
        setLevel1Options(response.data);
        setAllCodes(prev => {
          const filtered = prev.filter(c => c.depth !== 1);
          return [...filtered, ...response.data];
        });
      }
    } catch (error) {
      console.error("1단계 코드 로드 실패:", error);
    } finally {
      setLoading(prev => ({ ...prev, level1: false }));
    }
  }, [categoryCode, menuObjid]);

  // 2단계 코드 로드 (1단계 선택값 기준)
  const loadLevel2Codes = useCallback(async (parentCodeValue: string) => {
    if (!categoryCode || !parentCodeValue) {
      setLevel2Options([]);
      return;
    }
    
    setLoading(prev => ({ ...prev, level2: true }));
    try {
      const response = await commonCodeApi.hierarchy.getHierarchicalCodes(
        categoryCode,
        parentCodeValue,
        undefined,
        menuObjid
      );
      
      if (response.success && response.data) {
        setLevel2Options(response.data);
        setAllCodes(prev => {
          const filtered = prev.filter(c => c.depth !== 2 || (c.parentCodeValue || c.parent_code_value) !== parentCodeValue);
          return [...filtered, ...response.data];
        });
      }
    } catch (error) {
      console.error("2단계 코드 로드 실패:", error);
    } finally {
      setLoading(prev => ({ ...prev, level2: false }));
    }
  }, [categoryCode, menuObjid]);

  // 3단계 코드 로드 (2단계 선택값 기준)
  const loadLevel3Codes = useCallback(async (parentCodeValue: string) => {
    if (!categoryCode || !parentCodeValue) {
      setLevel3Options([]);
      return;
    }
    
    setLoading(prev => ({ ...prev, level3: true }));
    try {
      const response = await commonCodeApi.hierarchy.getHierarchicalCodes(
        categoryCode,
        parentCodeValue,
        undefined,
        menuObjid
      );
      
      if (response.success && response.data) {
        setLevel3Options(response.data);
        setAllCodes(prev => {
          const filtered = prev.filter(c => c.depth !== 3 || (c.parentCodeValue || c.parent_code_value) !== parentCodeValue);
          return [...filtered, ...response.data];
        });
      }
    } catch (error) {
      console.error("3단계 코드 로드 실패:", error);
    } finally {
      setLoading(prev => ({ ...prev, level3: false }));
    }
  }, [categoryCode, menuObjid]);

  // 초기 로드 및 카테고리 변경 시
  useEffect(() => {
    loadLevel1Codes();
    setSelectedLevel1("");
    setSelectedLevel2("");
    setSelectedLevel3("");
    setLevel2Options([]);
    setLevel3Options([]);
  }, [loadLevel1Codes]);

  // value prop 변경 시 역추적 (외부에서 값이 설정된 경우)
  useEffect(() => {
    if (!value || allCodes.length === 0) return;
    
    // 선택된 코드 찾기
    const selectedCode = allCodes.find(c => 
      (c.codeValue || c.code_value) === value
    );
    
    if (!selectedCode) return;
    
    const depth = selectedCode.depth || 1;
    
    if (depth === 1) {
      setSelectedLevel1(value);
      setSelectedLevel2("");
      setSelectedLevel3("");
    } else if (depth === 2) {
      const parentValue = selectedCode.parentCodeValue || selectedCode.parent_code_value || "";
      setSelectedLevel1(parentValue);
      setSelectedLevel2(value);
      setSelectedLevel3("");
      loadLevel2Codes(parentValue);
    } else if (depth === 3) {
      const parentValue = selectedCode.parentCodeValue || selectedCode.parent_code_value || "";
      
      // 2단계 부모 찾기
      const level2Code = allCodes.find(c => (c.codeValue || c.code_value) === parentValue);
      const level1Value = level2Code?.parentCodeValue || level2Code?.parent_code_value || "";
      
      setSelectedLevel1(level1Value);
      setSelectedLevel2(parentValue);
      setSelectedLevel3(value);
      
      loadLevel2Codes(level1Value);
      loadLevel3Codes(parentValue);
    }
  }, [value, allCodes]);

  // 1단계 선택 변경
  const handleLevel1Change = (codeValue: string) => {
    setSelectedLevel1(codeValue);
    setSelectedLevel2("");
    setSelectedLevel3("");
    setLevel2Options([]);
    setLevel3Options([]);
    
    if (codeValue && maxDepth > 1) {
      loadLevel2Codes(codeValue);
    }
    
    // 최대 깊이가 1이면 즉시 onChange 호출
    if (maxDepth === 1 && onChange) {
      const selectedCodeInfo = level1Options.find(c => (c.codeValue || c.code_value) === codeValue);
      onChange(codeValue, selectedCodeInfo, selectedCodeInfo ? [selectedCodeInfo] : []);
    }
  };

  // 2단계 선택 변경
  const handleLevel2Change = (codeValue: string) => {
    setSelectedLevel2(codeValue);
    setSelectedLevel3("");
    setLevel3Options([]);
    
    if (codeValue && maxDepth > 2) {
      loadLevel3Codes(codeValue);
    }
    
    // 최대 깊이가 2이면 onChange 호출
    if (maxDepth === 2 && onChange) {
      const level1Code = level1Options.find(c => (c.codeValue || c.code_value) === selectedLevel1);
      const level2Code = level2Options.find(c => (c.codeValue || c.code_value) === codeValue);
      const fullPath = [level1Code, level2Code].filter(Boolean) as CodeInfo[];
      onChange(codeValue, level2Code, fullPath);
    }
  };

  // 3단계 선택 변경
  const handleLevel3Change = (codeValue: string) => {
    setSelectedLevel3(codeValue);
    
    if (onChange) {
      const level1Code = level1Options.find(c => (c.codeValue || c.code_value) === selectedLevel1);
      const level2Code = level2Options.find(c => (c.codeValue || c.code_value) === selectedLevel2);
      const level3Code = level3Options.find(c => (c.codeValue || c.code_value) === codeValue);
      const fullPath = [level1Code, level2Code, level3Code].filter(Boolean) as CodeInfo[];
      onChange(codeValue, level3Code, fullPath);
    }
  };

  // 최종 선택값 계산
  const finalValue = useMemo(() => {
    if (maxDepth >= 3 && selectedLevel3) return selectedLevel3;
    if (maxDepth >= 2 && selectedLevel2) return selectedLevel2;
    if (selectedLevel1) return selectedLevel1;
    return "";
  }, [maxDepth, selectedLevel1, selectedLevel2, selectedLevel3]);

  // 최종 선택값이 변경되면 onChange 호출 (maxDepth 제한 없이)
  useEffect(() => {
    if (!onChange) return;
    
    // 현재 선택된 깊이 확인
    if (selectedLevel3 && maxDepth >= 3) {
      // 3단계까지 선택됨
      return; // handleLevel3Change에서 처리
    }
    if (selectedLevel2 && maxDepth >= 2 && !selectedLevel3 && level3Options.length === 0) {
      // 2단계까지 선택되고 3단계 옵션이 없음
      const level1Code = level1Options.find(c => (c.codeValue || c.code_value) === selectedLevel1);
      const level2Code = level2Options.find(c => (c.codeValue || c.code_value) === selectedLevel2);
      const fullPath = [level1Code, level2Code].filter(Boolean) as CodeInfo[];
      onChange(selectedLevel2, level2Code, fullPath);
    } else if (selectedLevel1 && maxDepth >= 1 && !selectedLevel2 && level2Options.length === 0) {
      // 1단계까지 선택되고 2단계 옵션이 없음
      const level1Code = level1Options.find(c => (c.codeValue || c.code_value) === selectedLevel1);
      onChange(selectedLevel1, level1Code, level1Code ? [level1Code] : []);
    }
  }, [level2Options, level3Options]);

  const containerClass = inline 
    ? "flex flex-wrap gap-4 items-end" 
    : "space-y-4";

  const selectItemClass = inline 
    ? "flex-1 min-w-[150px] space-y-1" 
    : "space-y-1";

  return (
    <div className={`${containerClass} ${className}`}>
      {/* 1단계 선택 */}
      <div className={selectItemClass}>
        <Label className="text-xs font-medium">
          {labels[0]}
          {required && <span className="ml-1 text-destructive">*</span>}
        </Label>
        <Select
          value={selectedLevel1}
          onValueChange={handleLevel1Change}
          disabled={disabled || loading.level1}
        >
          <SelectTrigger className="h-9 text-sm">
            {loading.level1 ? (
              <div className="flex items-center gap-2">
                <Loader2 className="h-3 w-3 animate-spin" />
                <span className="text-muted-foreground">로딩 중...</span>
              </div>
            ) : (
              <SelectValue placeholder={placeholders[0]} />
            )}
          </SelectTrigger>
          <SelectContent>
            {level1Options.map((code) => {
              const codeValue = code.codeValue || code.code_value || "";
              const codeName = code.codeName || code.code_name || "";
              return (
                <SelectItem key={codeValue} value={codeValue}>
                  {codeName}
                </SelectItem>
              );
            })}
          </SelectContent>
        </Select>
      </div>

      {/* 2단계 선택 */}
      {maxDepth >= 2 && (
        <div className={selectItemClass}>
          <Label className="text-xs font-medium">
            {labels[1] || "2단계"}
          </Label>
          <Select
            value={selectedLevel2}
            onValueChange={handleLevel2Change}
            disabled={disabled || loading.level2 || !selectedLevel1}
          >
            <SelectTrigger className="h-9 text-sm">
              {loading.level2 ? (
                <div className="flex items-center gap-2">
                  <Loader2 className="h-3 w-3 animate-spin" />
                  <span className="text-muted-foreground">로딩 중...</span>
                </div>
              ) : (
                <SelectValue placeholder={selectedLevel1 ? (placeholders[1] || "선택하세요") : "1단계를 먼저 선택하세요"} />
              )}
            </SelectTrigger>
            <SelectContent>
              {level2Options.length === 0 && selectedLevel1 && !loading.level2 ? (
                <div className="px-2 py-1.5 text-sm text-muted-foreground">
                  하위 항목이 없습니다
                </div>
              ) : (
                level2Options.map((code) => {
                  const codeValue = code.codeValue || code.code_value || "";
                  const codeName = code.codeName || code.code_name || "";
                  return (
                    <SelectItem key={codeValue} value={codeValue}>
                      {codeName}
                    </SelectItem>
                  );
                })
              )}
            </SelectContent>
          </Select>
        </div>
      )}

      {/* 3단계 선택 */}
      {maxDepth >= 3 && (
        <div className={selectItemClass}>
          <Label className="text-xs font-medium">
            {labels[2] || "3단계"}
          </Label>
          <Select
            value={selectedLevel3}
            onValueChange={handleLevel3Change}
            disabled={disabled || loading.level3 || !selectedLevel2}
          >
            <SelectTrigger className="h-9 text-sm">
              {loading.level3 ? (
                <div className="flex items-center gap-2">
                  <Loader2 className="h-3 w-3 animate-spin" />
                  <span className="text-muted-foreground">로딩 중...</span>
                </div>
              ) : (
                <SelectValue placeholder={selectedLevel2 ? (placeholders[2] || "선택하세요") : "2단계를 먼저 선택하세요"} />
              )}
            </SelectTrigger>
            <SelectContent>
              {level3Options.length === 0 && selectedLevel2 && !loading.level3 ? (
                <div className="px-2 py-1.5 text-sm text-muted-foreground">
                  하위 항목이 없습니다
                </div>
              ) : (
                level3Options.map((code) => {
                  const codeValue = code.codeValue || code.code_value || "";
                  const codeName = code.codeName || code.code_name || "";
                  return (
                    <SelectItem key={codeValue} value={codeValue}>
                      {codeName}
                    </SelectItem>
                  );
                })
              )}
            </SelectContent>
          </Select>
        </div>
      )}
    </div>
  );
}

export default HierarchicalCodeSelect;


