"use client";

/**
 * 외부 DB 소스 노드 속성 편집
 */

import { useEffect, useState } from "react";
import { Database, RefreshCw } from "lucide-react";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { useFlowEditorStore } from "@/lib/stores/flowEditorStore";
import {
  getTestedExternalConnections,
  getExternalTables,
  getExternalColumns,
  type ExternalConnection,
  type ExternalTable,
  type ExternalColumn,
} from "@/lib/api/nodeExternalConnections";
import { toast } from "sonner";
import type { ExternalDBSourceNodeData } from "@/types/node-editor";

interface ExternalDBSourcePropertiesProps {
  nodeId: string;
  data: ExternalDBSourceNodeData;
}

const DB_TYPE_INFO: Record<string, { label: string; color: string; icon: string }> = {
  postgresql: { label: "PostgreSQL", color: "#336791", icon: "🐘" },
  mysql: { label: "MySQL", color: "#4479A1", icon: "🐬" },
  oracle: { label: "Oracle", color: "#F80000", icon: "🔴" },
  mssql: { label: "MS SQL Server", color: "#CC2927", icon: "🏢" },
  mariadb: { label: "MariaDB", color: "#003545", icon: "🌊" },
};

export function ExternalDBSourceProperties({ nodeId, data }: ExternalDBSourcePropertiesProps) {
  const { updateNode, getExternalConnectionsCache, setExternalConnectionsCache } = useFlowEditorStore();

  const [displayName, setDisplayName] = useState(data.displayName || data.connectionName);
  const [selectedConnectionId, setSelectedConnectionId] = useState<number | undefined>(data.connectionId);
  const [tableName, setTableName] = useState(data.tableName);
  const [schema, setSchema] = useState(data.schema || "");

  const [connections, setConnections] = useState<ExternalConnection[]>([]);
  const [tables, setTables] = useState<ExternalTable[]>([]);
  const [columns, setColumns] = useState<ExternalColumn[]>([]);
  const [loadingConnections, setLoadingConnections] = useState(false);
  const [loadingTables, setLoadingTables] = useState(false);
  const [loadingColumns, setLoadingColumns] = useState(false);
  const [lastRefreshTime, setLastRefreshTime] = useState<number>(0); // 🔥 마지막 새로고침 시간
  const [remainingCooldown, setRemainingCooldown] = useState<number>(0); // 🔥 남은 쿨다운 시간

  const selectedConnection = connections.find((conn) => conn.id === selectedConnectionId);
  const dbInfo =
    selectedConnection && DB_TYPE_INFO[selectedConnection.db_type]
      ? DB_TYPE_INFO[selectedConnection.db_type]
      : {
          label: selectedConnection ? selectedConnection.db_type.toUpperCase() : "알 수 없음",
          color: "#666",
          icon: "💾",
        };

  // 🔥 첫 로드 시에만 커넥션 목록 로드 (전역 캐싱)
  useEffect(() => {
    const cachedData = getExternalConnectionsCache();
    if (cachedData) {
      console.log("✅ 캐시된 커넥션 사용:", cachedData.length);
      setConnections(cachedData);
    } else {
      console.log("🔄 API 호출하여 커넥션 로드");
      loadConnections();
    }
  }, []);

  // 커넥션 변경 시 테이블 목록 로드
  useEffect(() => {
    if (selectedConnectionId) {
      loadTables();
    }
  }, [selectedConnectionId]);

  // 테이블 변경 시 컬럼 목록 로드
  useEffect(() => {
    if (selectedConnectionId && tableName) {
      loadColumns();
    }
  }, [selectedConnectionId, tableName]);

  // 🔥 쿨다운 타이머 (1초마다 업데이트)
  useEffect(() => {
    const THROTTLE_DURATION = 10000; // 10초

    const timer = setInterval(() => {
      if (lastRefreshTime > 0) {
        const elapsed = Date.now() - lastRefreshTime;
        const remaining = Math.max(0, THROTTLE_DURATION - elapsed);
        setRemainingCooldown(Math.ceil(remaining / 1000));
      }
    }, 1000);

    return () => clearInterval(timer);
  }, [lastRefreshTime]);

  const loadConnections = async () => {
    // 🔥 쓰로틀링: 10초 이내 재요청 차단
    const THROTTLE_DURATION = 10000; // 10초
    const now = Date.now();

    if (now - lastRefreshTime < THROTTLE_DURATION) {
      const remainingSeconds = Math.ceil((THROTTLE_DURATION - (now - lastRefreshTime)) / 1000);
      toast.warning(`잠시 후 다시 시도해주세요 (${remainingSeconds}초 후)`);
      return;
    }

    setLoadingConnections(true);
    setLastRefreshTime(now); // 🔥 마지막 실행 시간 기록

    try {
      const data = await getTestedExternalConnections();
      setConnections(data);
      setExternalConnectionsCache(data); // 🔥 전역 캐시에 저장
      console.log("✅ 테스트 성공한 커넥션 로드 및 캐싱:", data.length);
      toast.success(`${data.length}개의 커넥션을 불러왔습니다.`);
    } catch (error) {
      console.error("❌ 커넥션 로드 실패:", error);
      toast.error("외부 DB 연결 목록을 불러올 수 없습니다.");
    } finally {
      setLoadingConnections(false);
    }
  };

  const loadTables = async () => {
    if (!selectedConnectionId) return;

    setLoadingTables(true);
    try {
      const data = await getExternalTables(selectedConnectionId);
      setTables(data);
      console.log("✅ 테이블 목록 로드:", data.length);
    } catch (error) {
      console.error("❌ 테이블 로드 실패:", error);
      toast.error("테이블 목록을 불러올 수 없습니다.");
    } finally {
      setLoadingTables(false);
    }
  };

  const loadColumns = async () => {
    if (!selectedConnectionId || !tableName) return;

    setLoadingColumns(true);
    try {
      const data = await getExternalColumns(selectedConnectionId, tableName);
      setColumns(data);
      console.log("✅ 컬럼 목록 로드:", data.length);

      // 노드에 outputFields 업데이트
      updateNode(nodeId, {
        outputFields: data.map((col) => ({
          name: col.column_name,
          type: col.data_type,
          label: col.column_name,
        })),
      });
    } catch (error) {
      console.error("❌ 컬럼 로드 실패:", error);
      toast.error("컬럼 목록을 불러올 수 없습니다.");
    } finally {
      setLoadingColumns(false);
    }
  };

  const handleConnectionChange = (connectionId: string) => {
    const id = parseInt(connectionId);
    setSelectedConnectionId(id);
    setTableName("");
    setTables([]);
    setColumns([]);

    const connection = connections.find((conn) => conn.id === id);
    if (connection) {
      updateNode(nodeId, {
        connectionId: id,
        connectionName: connection.connection_name,
        dbType: connection.db_type,
        displayName: connection.connection_name,
      });
    }
  };

  const handleTableChange = (newTableName: string) => {
    setTableName(newTableName);
    setColumns([]);

    updateNode(nodeId, {
      tableName: newTableName,
    });
  };

  const handleSave = () => {
    updateNode(nodeId, {
      displayName,
      connectionId: selectedConnectionId,
      connectionName: selectedConnection?.connection_name || "",
      tableName,
      schema,
      dbType: selectedConnection?.db_type,
    });
    toast.success("설정이 저장되었습니다.");
  };

  return (
    <ScrollArea className="h-full">
      <div className="space-y-4 p-4">
        {/* DB 타입 정보 */}
        <div
          className="rounded-lg border-2 p-4"
          style={{
            borderColor: dbInfo.color,
            backgroundColor: `${dbInfo.color}10`,
          }}
        >
          <div className="flex items-center gap-3">
            <div
              className="flex h-12 w-12 items-center justify-center rounded-lg"
              style={{ backgroundColor: dbInfo.color }}
            >
              <span className="text-2xl">{dbInfo.icon}</span>
            </div>
            <div>
              <p className="text-sm font-semibold" style={{ color: dbInfo.color }}>
                {dbInfo.label}
              </p>
              <p className="text-xs text-gray-600">외부 데이터베이스</p>
            </div>
          </div>
        </div>

        {/* 연결 선택 */}
        <div>
          <div className="mb-3 flex items-center justify-between">
            <h3 className="text-sm font-semibold">외부 DB 연결</h3>
            <Button
              size="sm"
              variant="ghost"
              onClick={loadConnections}
              disabled={loadingConnections || remainingCooldown > 0}
              className="relative h-7 px-2"
              title={
                loadingConnections
                  ? "테스트 진행 중..."
                  : remainingCooldown > 0
                    ? `${remainingCooldown}초 후 재시도 가능`
                    : "연결 테스트 재실행 (10초 간격 제한)"
              }
            >
              <RefreshCw className={`h-3 w-3 ${loadingConnections ? "animate-spin" : ""}`} />
              {remainingCooldown > 0 && !loadingConnections && (
                <span className="absolute -top-1 -right-1 flex h-4 w-4 items-center justify-center rounded-full bg-orange-500 text-[9px] text-white">
                  {remainingCooldown}
                </span>
              )}
            </Button>
          </div>

          <div className="space-y-3">
            <div>
              <Label className="text-xs">연결 선택 (테스트 성공한 커넥션만 표시)</Label>
              <Select
                value={selectedConnectionId?.toString()}
                onValueChange={handleConnectionChange}
                disabled={loadingConnections}
              >
                <SelectTrigger className="mt-1">
                  <SelectValue placeholder="외부 DB 연결 선택..." />
                </SelectTrigger>
                <SelectContent>
                  {connections.map((conn) => (
                    <SelectItem key={conn.id} value={conn.id.toString()}>
                      <div className="flex items-center gap-2">
                        <span>{DB_TYPE_INFO[conn.db_type]?.icon || "💾"}</span>
                        <span>{conn.connection_name}</span>
                        <span className="text-xs text-gray-500">({conn.db_type})</span>
                      </div>
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              {loadingConnections && <p className="mt-1 text-xs text-gray-500">테스트 중... ⏳</p>}
              {connections.length === 0 && !loadingConnections && (
                <p className="mt-1 text-xs text-orange-600">⚠️ 테스트에 성공한 커넥션이 없습니다.</p>
              )}
            </div>

            <div>
              <Label htmlFor="displayName" className="text-xs">
                표시 이름
              </Label>
              <Input
                id="displayName"
                value={displayName}
                onChange={(e) => setDisplayName(e.target.value)}
                className="mt-1"
                placeholder="노드 표시 이름"
              />
            </div>
          </div>
        </div>

        {/* 테이블 선택 */}
        {selectedConnectionId && (
          <div>
            <h3 className="mb-3 text-sm font-semibold">테이블 선택</h3>

            <div className="space-y-3">
              <div>
                <Label className="text-xs">테이블명</Label>
                <Select value={tableName} onValueChange={handleTableChange} disabled={loadingTables}>
                  <SelectTrigger className="mt-1">
                    <SelectValue placeholder="테이블 선택..." />
                  </SelectTrigger>
                  <SelectContent>
                    {tables.map((table) => (
                      <SelectItem key={table.table_name} value={table.table_name}>
                        <div className="flex items-center gap-2">
                          <span>📋</span>
                          <span>{table.table_name}</span>
                          {table.schema && <span className="text-xs text-gray-500">({table.schema})</span>}
                        </div>
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                {loadingTables && <p className="mt-1 text-xs text-gray-500">테이블 목록 로딩 중... ⏳</p>}
              </div>
            </div>
          </div>
        )}

        {/* 컬럼 정보 */}
        {columns.length > 0 && (
          <div>
            <h3 className="mb-3 text-sm font-semibold">출력 필드 ({columns.length}개)</h3>
            {loadingColumns ? (
              <p className="text-xs text-gray-500">컬럼 목록 로딩 중... ⏳</p>
            ) : (
              <div className="max-h-[200px] space-y-1 overflow-y-auto">
                {columns.map((col, index) => (
                  <div
                    key={index}
                    className="flex items-center justify-between rounded border bg-gray-50 px-3 py-2 text-xs"
                  >
                    <span className="font-medium">{col.column_name}</span>
                    <span className="font-mono text-gray-500">{col.data_type}</span>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}

        <Button onClick={handleSave} className="w-full" size="sm">
          적용
        </Button>

        <div className="rounded p-3 text-xs" style={{ backgroundColor: `${dbInfo.color}15`, color: dbInfo.color }}>
          💡 외부 DB 연결은 "외부 DB 연결 관리" 메뉴에서 미리 설정해야 합니다.
        </div>
      </div>
    </ScrollArea>
  );
}
