"use client";

import React, { useState, useRef, useEffect, useCallback } from "react";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Search, Link, Unlink } from "lucide-react";
import { toast } from "sonner";

// 타입 import
import { ColumnInfo } from "@/lib/types/multiConnection";
import { FieldMapping, FieldMappingCanvasProps } from "../../types/redesigned";

// 컴포넌트 import
import FieldColumn from "./FieldColumn";
import MappingControls from "./MappingControls";

/**
 * 🎨 시각적 필드 매핑 캔버스
 * - SVG 기반 연결선 표시
 * - 드래그 앤 드롭 지원 (향후)
 * - 실시간 연결선 업데이트
 */
const FieldMappingCanvas: React.FC<FieldMappingCanvasProps> = ({
  fromFields,
  toFields,
  mappings,
  onCreateMapping,
  onDeleteMapping,
}) => {
  const [fromSearch, setFromSearch] = useState("");
  const [toSearch, setToSearch] = useState("");
  const [selectedFromField, setSelectedFromField] = useState<ColumnInfo | null>(null);
  const [selectedToField, setSelectedToField] = useState<ColumnInfo | null>(null);
  const [fieldPositions, setFieldPositions] = useState<Record<string, { x: number; y: number }>>({});

  // 드래그 앤 드롭 상태
  const [draggedField, setDraggedField] = useState<ColumnInfo | null>(null);
  const [isDragOver, setIsDragOver] = useState(false);

  const canvasRef = useRef<HTMLDivElement>(null);
  const fromColumnRef = useRef<HTMLDivElement>(null);
  const toColumnRef = useRef<HTMLDivElement>(null);
  const fieldRefs = useRef<Record<string, HTMLElement>>({});

  // 필드 필터링 - 안전한 배열 처리
  const safeFromFields = Array.isArray(fromFields) ? fromFields : [];
  const safeToFields = Array.isArray(toFields) ? toFields : [];

  const filteredFromFields = safeFromFields.filter((field) => {
    const fieldName = field.displayName || field.columnName || "";
    return fieldName.toLowerCase().includes(fromSearch.toLowerCase());
  });

  const filteredToFields = safeToFields.filter((field) => {
    const fieldName = field.displayName || field.columnName || "";
    return fieldName.toLowerCase().includes(toSearch.toLowerCase());
  });

  // 매핑 생성
  const handleCreateMapping = useCallback(() => {
    if (selectedFromField && selectedToField) {
      // 안전한 매핑 배열 처리
      const safeMappings = Array.isArray(mappings) ? mappings : [];

      // N:1 매핑 방지 - TO 필드가 이미 매핑되어 있는지 확인
      const existingToMapping = safeMappings.find((m) => m.toField.columnName === selectedToField.columnName);

      if (existingToMapping) {
        toast.error(
          `대상 필드 '${selectedToField.displayName || selectedToField.columnName}'는 이미 매핑되어 있습니다.\nN:1 매핑은 허용되지 않습니다.`,
        );
        setSelectedFromField(null);
        setSelectedToField(null);
        return;
      }

      // 동일한 매핑 중복 체크
      const existingMapping = safeMappings.find(
        (m) =>
          m.fromField.columnName === selectedFromField.columnName &&
          m.toField.columnName === selectedToField.columnName,
      );

      if (existingMapping) {
        setSelectedFromField(null);
        setSelectedToField(null);
        return;
      }

      onCreateMapping(selectedFromField, selectedToField);
      setSelectedFromField(null);
      setSelectedToField(null);
    }
  }, [selectedFromField, selectedToField, mappings, onCreateMapping]);

  // 드래그 앤 드롭 핸들러들
  const handleDragStart = useCallback((field: ColumnInfo) => {
    setDraggedField(field);
    setSelectedFromField(field); // 드래그 시작 시 선택 상태로 표시
  }, []);

  const handleDragEnd = useCallback(() => {
    setDraggedField(null);
    setIsDragOver(false);
  }, []);

  // 드래그 오버 상태 관리
  useEffect(() => {
    if (draggedField) {
      setIsDragOver(true);
    } else {
      setIsDragOver(false);
    }
  }, [draggedField]);

  const handleDrop = useCallback(
    (targetField: ColumnInfo, sourceField: ColumnInfo) => {
      // 안전한 매핑 배열 처리
      const safeMappings = Array.isArray(mappings) ? mappings : [];

      // N:1 매핑 방지 - TO 필드가 이미 매핑되어 있는지 확인
      const existingToMapping = safeMappings.find((m) => m.toField.columnName === targetField.columnName);

      if (existingToMapping) {
        toast.error(
          `대상 필드 '${targetField.displayName || targetField.columnName}'는 이미 매핑되어 있습니다.\nN:1 매핑은 허용되지 않습니다.`,
        );
        setDraggedField(null);
        setIsDragOver(false);
        return;
      }

      // 동일한 매핑 중복 체크
      const existingMapping = mappings.find(
        (m) => m.fromField.columnName === sourceField.columnName && m.toField.columnName === targetField.columnName,
      );

      if (existingMapping) {
        setDraggedField(null);
        setIsDragOver(false);
        return;
      }

      // 매핑 생성
      onCreateMapping(sourceField, targetField);

      // 상태 초기화
      setDraggedField(null);
      setIsDragOver(false);
      setSelectedFromField(null);
      setSelectedToField(null);
    },
    [mappings, onCreateMapping],
  );

  // 필드 위치 업데이트 (메모이제이션)
  const updateFieldPosition = useCallback((fieldId: string, element: HTMLElement) => {
    if (!canvasRef.current) return;

    // fieldRefs에 저장
    fieldRefs.current[fieldId] = element;

    const canvasRect = canvasRef.current.getBoundingClientRect();
    const fieldRect = element.getBoundingClientRect();

    const x = fieldRect.left - canvasRect.left + fieldRect.width / 2;
    const y = fieldRect.top - canvasRect.top + fieldRect.height / 2;

    setFieldPositions((prev) => {
      // 위치가 실제로 변경된 경우에만 업데이트
      const currentPos = prev[fieldId];
      if (currentPos && Math.abs(currentPos.x - x) < 1 && Math.abs(currentPos.y - y) < 1) {
        return prev;
      }

      return {
        ...prev,
        [fieldId]: { x, y },
      };
    });
  }, []);

  // 스크롤 이벤트 리스너로 연결선 위치 업데이트
  useEffect(() => {
    const updatePositionsOnScroll = () => {
      // 모든 필드의 위치를 다시 계산
      Object.entries(fieldRefs.current || {}).forEach(([fieldId, element]) => {
        if (element) {
          updateFieldPosition(fieldId, element);
        }
      });
    };

    // 스크롤 가능한 영역들에 이벤트 리스너 추가
    const scrollAreas = document.querySelectorAll("[data-radix-scroll-area-viewport]");

    scrollAreas.forEach((area) => {
      area.addEventListener("scroll", updatePositionsOnScroll, { passive: true });
    });

    // 윈도우 리사이즈 시에도 위치 업데이트
    window.addEventListener("resize", updatePositionsOnScroll, { passive: true });

    return () => {
      scrollAreas.forEach((area) => {
        area.removeEventListener("scroll", updatePositionsOnScroll);
      });
      window.removeEventListener("resize", updatePositionsOnScroll);
    };
  }, [updateFieldPosition]);

  // 매핑 여부 확인
  const isFieldMapped = useCallback(
    (field: ColumnInfo, type: "from" | "to") => {
      return mappings
        .filter((mapping) => mapping.fromField && mapping.toField) // 유효한 매핑만 확인
        .some((mapping) =>
          type === "from"
            ? mapping.fromField?.columnName === field.columnName
            : mapping.toField?.columnName === field.columnName,
        );
    },
    [mappings],
  );

  // 연결선 데이터 생성

  return (
    <div ref={canvasRef} className="relative flex h-full flex-col">
      {/* 매핑 생성 컨트롤 */}
      <div className="mb-4 flex-shrink-0">
        <MappingControls
          selectedFromField={selectedFromField}
          selectedToField={selectedToField}
          onCreateMapping={handleCreateMapping}
          canCreate={!!(selectedFromField && selectedToField)}
        />
      </div>

      {/* 필드 매핑 영역 */}
      <div className="grid max-h-[500px] min-h-[300px] flex-1 grid-cols-2 gap-6 overflow-hidden">
        {/* FROM 필드 컬럼 */}
        <div ref={fromColumnRef} className="flex h-full flex-col">
          <div className="mb-3 flex flex-shrink-0 items-center justify-between">
            <h3 className="font-medium">FROM 필드</h3>
            <Badge variant="outline" className="text-xs">
              {filteredFromFields.length}개
            </Badge>
          </div>

          <div className="relative mb-3 flex-shrink-0">
            <Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 transform" />
            <Input
              placeholder="필드 검색..."
              value={fromSearch}
              onChange={(e) => setFromSearch(e.target.value)}
              className="h-8 pl-9"
            />
          </div>

          <div className="max-h-[400px] min-h-0 flex-1">
            <FieldColumn
              fields={filteredFromFields}
              type="from"
              selectedField={selectedFromField}
              onFieldSelect={setSelectedFromField}
              onFieldPositionUpdate={updateFieldPosition}
              isFieldMapped={isFieldMapped}
              onDragStart={handleDragStart}
              onDragEnd={handleDragEnd}
              draggedField={draggedField}
            />
          </div>
        </div>

        {/* TO 필드 컬럼 */}
        <div ref={toColumnRef} className="flex h-full flex-col">
          <div className="mb-3 flex flex-shrink-0 items-center justify-between">
            <h3 className="font-medium">TO 필드</h3>
            <Badge variant="outline" className="text-xs">
              {filteredToFields.length}개
            </Badge>
          </div>

          <div className="relative mb-3 flex-shrink-0">
            <Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 transform" />
            <Input
              placeholder="필드 검색..."
              value={toSearch}
              onChange={(e) => setToSearch(e.target.value)}
              className="h-8 pl-9"
            />
          </div>

          <div className="max-h-[400px] min-h-0 flex-1">
            <FieldColumn
              fields={filteredToFields}
              type="to"
              selectedField={selectedToField}
              onFieldSelect={setSelectedToField}
              onFieldPositionUpdate={updateFieldPosition}
              isFieldMapped={isFieldMapped}
              onDrop={handleDrop}
              isDragOver={isDragOver}
              draggedField={draggedField}
            />
          </div>
        </div>
      </div>

      {/* 매핑 규칙 안내 */}
      <div className="mt-4 rounded-lg border border-primary/20 bg-accent p-3">
        <h4 className="mb-2 text-sm font-medium">📋 매핑 규칙</h4>
        <div className="text-muted-foreground space-y-1 text-xs">
          <p>✅ 1:N 매핑 허용 (하나의 소스 필드를 여러 대상 필드에 매핑)</p>
          <p>❌ N:1 매핑 금지 (여러 소스 필드를 하나의 대상 필드에 매핑 불가)</p>
          <p>🔒 이미 매핑된 대상 필드는 추가 매핑이 차단됩니다</p>
          <p>🔗 {mappings.length}개 연결됨</p>
        </div>
      </div>
    </div>
  );
};

export default FieldMappingCanvas;
