"use client";

import React, { useState, useEffect, useRef, useMemo } from "react";
import { ArrowLeftRight } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
} from "@/components/ui/select";
import { cn } from "@/lib/utils";
import { apiClient } from "@/lib/api/client";

interface LocationOption {
  value: string;
  label: string;
}

interface DataSourceConfig {
  type: "table" | "code" | "static";
  tableName?: string;
  valueField?: string;
  labelField?: string;
  codeInfo?: string;
  staticOptions?: LocationOption[];
}

const DEFAULT_OPTIONS: LocationOption[] = [
  { value: "포항", label: "포항" },
  { value: "광양", label: "광양" },
];
const DEFAULT_STATIC_FALLBACK: DataSourceConfig = { type: "static", staticOptions: [] };

// 모듈 레벨 캐시 — 컴포넌트 리마운트에도 유지
const dbLoadCache = new Map<string, { departure: string; destination: string } | null>();

export interface LocationSwapSelectorProps {
  id?: string;
  style?: React.CSSProperties;
  isDesignMode?: boolean;
  dataSource?: DataSourceConfig;
  departureField?: string;
  destinationField?: string;
  departureLabelField?: string;
  destinationLabelField?: string;
  departureLabel?: string;
  destinationLabel?: string;
  showSwapButton?: boolean;
  swapButtonPosition?: "center" | "right";
  variant?: "card" | "inline" | "minimal";
  formData?: Record<string, any>;
  onFormDataChange?: (field: string, value: any) => void;
  userId?: string;
  componentConfig?: {
    dataSource?: DataSourceConfig;
    departureField?: string;
    destinationField?: string;
    departureLabelField?: string;
    destinationLabelField?: string;
    departureLabel?: string;
    destinationLabel?: string;
    showSwapButton?: boolean;
    swapButtonPosition?: "center" | "right";
    variant?: "card" | "inline" | "minimal";
    loadFromDb?: boolean;
    dbTableName?: string;
    dbKeyField?: string;
  };
  // DynamicComponentRenderer에서 전달되는 추가 props (무시)
  [key: string]: any;
}

export function LocationSwapSelectorComponent(props: LocationSwapSelectorProps) {
  const {
    id,
    style,
    isDesignMode = false,
    formData,
    onFormDataChange,
    componentConfig,
    userId,
  } = props;

  // 안전한 formData 참조 — undefined면 빈 객체 사용하되 매번 새로 만들지 않음
  const safeFormData = formData || {};

  const config = componentConfig || {};
  const dataSource = config.dataSource || props.dataSource || DEFAULT_STATIC_FALLBACK;
  const departureField = config.departureField || props.departureField || "departure";
  const destinationField = config.destinationField || props.destinationField || "destination";
  const departureLabelField = config.departureLabelField || props.departureLabelField;
  const destinationLabelField = config.destinationLabelField || props.destinationLabelField;
  const departureLabel = config.departureLabel || props.departureLabel || "출발지";
  const destinationLabel = config.destinationLabel || props.destinationLabel || "도착지";
  const showSwapButton = config.showSwapButton !== false && props.showSwapButton !== false;
  const variant = config.variant || props.variant || "card";

  const loadFromDb = config.loadFromDb !== false;
  const dbTableName = config.dbTableName || "vehicles";
  const dbKeyField = config.dbKeyField || "user_id";

  const [options, setOptions] = useState<LocationOption[]>(DEFAULT_OPTIONS);
  const [loading, setLoading] = useState(false);
  const [isSwapping, setIsSwapping] = useState(false);

  // formData에서 직접 읽기 — 이중 상태 없음
  const currentDeparture = safeFormData[departureField] || "";
  const currentDestination = safeFormData[destinationField] || "";

  // refs
  const onFormDataChangeRef = useRef(onFormDataChange);
  onFormDataChangeRef.current = onFormDataChange;
  const mountedRef = useRef(true);
  useEffect(() => {
    mountedRef.current = true;
    return () => { mountedRef.current = false; };
  }, []);

  // --- 옵션 로드 ---
  const dataSourceKey = useMemo(() => JSON.stringify(dataSource), [dataSource]);

  useEffect(() => {
    let cancelled = false;

    const loadOptions = async () => {
      const shouldUseStatic =
        !dataSource.type ||
        dataSource.type === "static" ||
        (dataSource.type === "table" && !dataSource.tableName) ||
        (dataSource.type === "code" && !dataSource.codeInfo);

      if (shouldUseStatic) {
        const staticOpts = dataSource.staticOptions || [];
        const isValid = staticOpts.length > 0 &&
          staticOpts[0]?.value &&
          staticOpts[0].value !== departureField &&
          staticOpts[0].value !== destinationField;
        if (!cancelled) setOptions(isValid ? staticOpts : DEFAULT_OPTIONS);
        return;
      }

      if (dataSource.type === "code" && dataSource.codeInfo) {
        if (!cancelled) setLoading(true);
        try {
          const response = await apiClient.get(`/code-management/codes`, {
            params: { categoryCode: dataSource.codeInfo },
          });
          if (!cancelled && response.data.success && response.data.data) {
            setOptions(response.data.data.map((code: any) => ({
              value: code.code_value || code.codeValue || code.code,
              label: code.code_name || code.codeName || code.name,
            })));
          }
        } catch (error) {
          console.error("코드 로드 실패:", error);
        } finally {
          if (!cancelled) setLoading(false);
        }
        return;
      }

      if (dataSource.type === "table" && dataSource.tableName) {
        if (!cancelled) setLoading(true);
        try {
          const response = await apiClient.get(`/dynamic-form/list/${dataSource.tableName}`, {
            params: { page: 1, pageSize: 1000 },
          });
          if (!cancelled && response.data.success && response.data.data) {
            const rows = Array.isArray(response.data.data)
              ? response.data.data
              : response.data.data.rows || [];
            setOptions(rows.map((row: any) => ({
              value: String(row[dataSource.valueField || "id"] || ""),
              label: String(row[dataSource.labelField || "name"] || ""),
            })));
          }
        } catch (error) {
          console.error("테이블 데이터 로드 실패:", error);
        } finally {
          if (!cancelled) setLoading(false);
        }
      }
    };

    loadOptions();
    return () => { cancelled = true; };
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [dataSourceKey, isDesignMode]);

  // --- DB 초기값 로드 (모듈 캐시로 1회 보장) ---
  useEffect(() => {
    if (isDesignMode || !loadFromDb || !userId || options.length === 0) return;

    const cacheKey = `${dbTableName}:${dbKeyField}:${userId}`;

    // 이미 로드 시도함
    if (dbLoadCache.has(cacheKey)) {
      const cached = dbLoadCache.get(cacheKey);
      if (cached) {
        const cb = onFormDataChangeRef.current;
        if (cached.departure && options.some(o => o.value === cached.departure)) {
          cb?.(departureField, cached.departure);
          if (departureLabelField) {
            const opt = options.find(o => o.value === cached.departure);
            if (opt) cb?.(departureLabelField, opt.label);
          }
        }
        if (cached.destination && options.some(o => o.value === cached.destination)) {
          cb?.(destinationField, cached.destination);
          if (destinationLabelField) {
            const opt = options.find(o => o.value === cached.destination);
            if (opt) cb?.(destinationLabelField, opt.label);
          }
        }
      }
      return;
    }

    // 로드 시작 전 캐시에 null 마킹 (중복 방지)
    dbLoadCache.set(cacheKey, null);

    const loadFromDatabase = async () => {
      try {
        const response = await apiClient.post(
          `/table-management/tables/${dbTableName}/data`,
          { page: 1, size: 1, search: { [dbKeyField]: userId }, autoFilter: true }
        );

        const vehicleData = response.data?.data?.data?.[0] || response.data?.data?.rows?.[0];
        if (!vehicleData) return;

        const dbDeparture = vehicleData[departureField] || vehicleData.departure || "";
        const dbDestination = vehicleData[destinationField] || vehicleData.arrival || vehicleData.destination || "";

        // 캐시 저장
        dbLoadCache.set(cacheKey, { departure: dbDeparture, destination: dbDestination });

        if (!mountedRef.current) return;
        const cb = onFormDataChangeRef.current;
        if (dbDeparture && options.some(o => o.value === dbDeparture)) {
          cb?.(departureField, dbDeparture);
          if (departureLabelField) {
            const opt = options.find(o => o.value === dbDeparture);
            if (opt) cb?.(departureLabelField, opt.label);
          }
        }
        if (dbDestination && options.some(o => o.value === dbDestination)) {
          cb?.(destinationField, dbDestination);
          if (destinationLabelField) {
            const opt = options.find(o => o.value === dbDestination);
            if (opt) cb?.(destinationLabelField, opt.label);
          }
        }
      } catch (error) {
        console.error("[LocationSwapSelector] DB 로드 실패:", error);
      }
    };

    loadFromDatabase();
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [userId, options.length]);

  // --- 이벤트 핸들러 ---
  const handleDepartureChange = (selectedValue: string) => {
    if (!onFormDataChange || selectedValue === currentDeparture) return;
    onFormDataChange(departureField, selectedValue);
    if (departureLabelField) {
      const opt = options.find(o => o.value === selectedValue);
      if (opt) onFormDataChange(departureLabelField, opt.label);
    }
  };

  const handleDestinationChange = (selectedValue: string) => {
    if (!onFormDataChange || selectedValue === currentDestination) return;
    onFormDataChange(destinationField, selectedValue);
    if (destinationLabelField) {
      const opt = options.find(o => o.value === selectedValue);
      if (opt) onFormDataChange(destinationLabelField, opt.label);
    }
  };

  const handleSwap = () => {
    if (!onFormDataChange) return;
    setIsSwapping(true);
    onFormDataChange(departureField, currentDestination);
    onFormDataChange(destinationField, currentDeparture);
    if (departureLabelField && destinationLabelField) {
      const depOpt = options.find(o => o.value === currentDestination);
      const destOpt = options.find(o => o.value === currentDeparture);
      onFormDataChange(departureLabelField, depOpt?.label || "");
      onFormDataChange(destinationLabelField, destOpt?.label || "");
    }
    setTimeout(() => setIsSwapping(false), 300);
  };

  const { width, height, ...restStyle } = style || {};
  const depLabel = options.find(o => o.value === currentDeparture)?.label || "";
  const destLabel = options.find(o => o.value === currentDestination)?.label || "";

  // Select에 전달할 값 — 빈 문자열이면 undefined (uncontrolled)
  const selectDepValue = currentDeparture || undefined;
  const selectDestValue = currentDestination || undefined;

  if (variant === "card") {
    return (
      <div id={id} className="h-full w-full" style={restStyle}>
        <div className="flex items-center justify-between rounded-lg border bg-card p-4 shadow-sm">
          <div className="flex flex-1 flex-col items-center">
            <span className="mb-1 text-xs text-muted-foreground">{departureLabel}</span>
            <Select value={selectDepValue} onValueChange={handleDepartureChange} disabled={loading}>
              <SelectTrigger className={cn(
                "h-auto w-full max-w-[120px] border-0 bg-transparent p-0 text-center text-lg font-bold shadow-none focus:ring-0",
                isSwapping && "animate-pulse"
              )}>
                {currentDeparture
                  ? <span>{depLabel}</span>
                  : <span className="text-muted-foreground">선택</span>}
              </SelectTrigger>
              <SelectContent position="popper" sideOffset={4}>
                {options.map((option) => (
                  <SelectItem key={option.value} value={option.value} disabled={option.value === currentDestination}>
                    {option.label}{option.value === currentDestination && " (도착지)"}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          {showSwapButton && (
            <Button type="button" variant="ghost" size="icon" onClick={handleSwap}
              className={cn("mx-2 h-10 w-10 rounded-full border bg-background transition-transform hover:bg-muted", isSwapping && "rotate-180")}>
              <ArrowLeftRight className="h-5 w-5 text-muted-foreground" />
            </Button>
          )}

          <div className="flex flex-1 flex-col items-center">
            <span className="mb-1 text-xs text-muted-foreground">{destinationLabel}</span>
            <Select value={selectDestValue} onValueChange={handleDestinationChange} disabled={loading}>
              <SelectTrigger className={cn(
                "h-auto w-full max-w-[120px] border-0 bg-transparent p-0 text-center text-lg font-bold shadow-none focus:ring-0",
                isSwapping && "animate-pulse"
              )}>
                {currentDestination
                  ? <span>{destLabel}</span>
                  : <span className="text-muted-foreground">선택</span>}
              </SelectTrigger>
              <SelectContent position="popper" sideOffset={4}>
                {options.map((option) => (
                  <SelectItem key={option.value} value={option.value} disabled={option.value === currentDeparture}>
                    {option.label}{option.value === currentDeparture && " (출발지)"}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        </div>
      </div>
    );
  }

  if (variant === "inline") {
    return (
      <div id={id} className="flex h-full w-full items-center gap-2" style={restStyle}>
        <div className="flex-1">
          <label className="mb-1 block text-xs text-muted-foreground">{departureLabel}</label>
          <Select value={selectDepValue} onValueChange={handleDepartureChange} disabled={loading}>
            <SelectTrigger className="h-10">
              {currentDeparture ? depLabel : <span className="text-muted-foreground">선택</span>}
            </SelectTrigger>
            <SelectContent position="popper" sideOffset={4}>
              {options.map((option) => (
                <SelectItem key={option.value} value={option.value} disabled={option.value === currentDestination}>
                  {option.label}{option.value === currentDestination && " (도착지)"}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
        {showSwapButton && (
          <Button type="button" variant="outline" size="icon" onClick={handleSwap} className="mt-5 h-10 w-10">
            <ArrowLeftRight className="h-4 w-4" />
          </Button>
        )}
        <div className="flex-1">
          <label className="mb-1 block text-xs text-muted-foreground">{destinationLabel}</label>
          <Select value={selectDestValue} onValueChange={handleDestinationChange} disabled={loading}>
            <SelectTrigger className="h-10">
              {currentDestination ? destLabel : <span className="text-muted-foreground">선택</span>}
            </SelectTrigger>
            <SelectContent position="popper" sideOffset={4}>
              {options.map((option) => (
                <SelectItem key={option.value} value={option.value} disabled={option.value === currentDeparture}>
                  {option.label}{option.value === currentDeparture && " (출발지)"}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
      </div>
    );
  }

  return (
    <div id={id} className="flex h-full w-full items-center gap-1" style={restStyle}>
      <Select value={selectDepValue} onValueChange={handleDepartureChange} disabled={loading}>
        <SelectTrigger className="h-8 flex-1 text-sm">
          {currentDeparture ? depLabel : <span className="text-muted-foreground">{departureLabel}</span>}
        </SelectTrigger>
        <SelectContent position="popper" sideOffset={4}>
          {options.map((option) => (
            <SelectItem key={option.value} value={option.value} disabled={option.value === currentDestination}>
              {option.label}{option.value === currentDestination && " (도착지)"}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
      {showSwapButton && (
        <Button type="button" variant="ghost" size="sm" onClick={handleSwap} className="h-8 w-8 p-0">
          <ArrowLeftRight className="h-4 w-4" />
        </Button>
      )}
      <Select value={selectDestValue} onValueChange={handleDestinationChange} disabled={loading}>
        <SelectTrigger className="h-8 flex-1 text-sm">
          {currentDestination ? destLabel : <span className="text-muted-foreground">{destinationLabel}</span>}
        </SelectTrigger>
        <SelectContent position="popper" sideOffset={4}>
          {options.map((option) => (
            <SelectItem key={option.value} value={option.value} disabled={option.value === currentDeparture}>
              {option.label}{option.value === currentDeparture && " (출발지)"}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
    </div>
  );
}
