"use client";

import React, { useState, useEffect, useMemo, useCallback, useRef } from "react";
import {
  Dialog,
  DialogContent,
  DialogTitle,
  DialogDescription,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { useUnsavedChangesGuard, UnsavedChangesDialog } from "@/components/common/UnsavedChangesGuard";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  LayoutGrid,
  Database,
  Palette,
  X,
  Type,
  CreditCard,
  Minus,
  Tag,
} from "lucide-react";
import { reportApi } from "@/lib/api/reportApi";
import type {
  CardLayoutConfig,
  CardLayoutRow,
  CardElement,
  CardDataCellElement,
  CardBadgeElement,
} from "@/types/report";
import { CardElementPalette } from "./CardElementPalette";
import { CardCanvasEditor } from "./CardCanvasEditor";

interface CardLayoutModalProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  initialConfig?: CardLayoutConfig;
  onSave: (config: CardLayoutConfig) => void;
}

type TabType = "layout" | "binding" | "style";

interface TableInfo {
  table_name: string;
  table_type: string;
}

interface ColumnInfo {
  column_name: string;
  data_type: string;
  is_nullable: string;
}

const generateId = () =>
  `row_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;

const DEFAULT_CONFIG: CardLayoutConfig = {
  tableName: "",
  primaryKey: "",
  rows: [
    {
      id: generateId(),
      gridColumns: 4,
      elements: [],
    },
  ],
  padding: "12px",
  gap: "8px",
  borderStyle: "solid",
  borderColor: "#e5e7eb",
  backgroundColor: "#ffffff",
  headerTitleFontSize: 14,
  headerTitleColor: "#1e40af",
  labelFontSize: 13,
  labelColor: "#374151",
  valueFontSize: 13,
  valueColor: "#000000",
  dividerThickness: 1,
  dividerColor: "#e5e7eb",
};

const getElementIcon = (type: string) => {
  switch (type) {
    case "header":
      return <Type className="w-3 h-3" />;
    case "dataCell":
      return <CreditCard className="w-3 h-3" />;
    case "divider":
      return <Minus className="w-3 h-3" />;
    case "badge":
      return <Tag className="w-3 h-3" />;
    default:
      return null;
  }
};

export function CardLayoutModal({
  open,
  onOpenChange,
  initialConfig,
  onSave,
}: CardLayoutModalProps) {
  const [activeTab, setActiveTab] = useState<TabType>("layout");
  const [config, setConfig] = useState<CardLayoutConfig>(
    initialConfig || DEFAULT_CONFIG,
  );
  const [tables, setTables] = useState<TableInfo[]>([]);
  const [columns, setColumns] = useState<ColumnInfo[]>([]);
  const [loadingTables, setLoadingTables] = useState(false);
  const [loadingColumns, setLoadingColumns] = useState(false);
  const initialSnapshotRef = useRef<string>("");

  const hasChanges = useCallback(() => {
    return JSON.stringify(config) !== initialSnapshotRef.current;
  }, [config]);

  const guard = useUnsavedChangesGuard({
    hasChanges,
    onClose: () => onOpenChange(false),
  });

  useEffect(() => {
    if (open) {
      const initConfig = initialConfig || DEFAULT_CONFIG;
      setConfig(initConfig);
      initialSnapshotRef.current = JSON.stringify(initConfig);
      setActiveTab("layout");
      fetchTables();
    }
  }, [open, initialConfig]);

  useEffect(() => {
    if (config.tableName) {
      fetchColumns(config.tableName);
    } else {
      setColumns([]);
    }
  }, [config.tableName]);

  const fetchTables = async () => {
    setLoadingTables(true);
    try {
      const response = await reportApi.getSchemaTableList();
      if (response.success) {
        setTables(response.data);
      }
    } catch (error) {
      console.error("테이블 목록 조회 실패:", error);
    } finally {
      setLoadingTables(false);
    }
  };

  const fetchColumns = async (tableName: string) => {
    setLoadingColumns(true);
    try {
      const response = await reportApi.getSchemaTableColumns(tableName);
      if (response.success) {
        setColumns(response.data);
        const pkCandidate = response.data.find(
          (col) =>
            col.column_name.endsWith("_id") ||
            col.column_name === "id" ||
            col.column_name.endsWith("_pk"),
        );
        if (pkCandidate && !config.primaryKey) {
          setConfig((prev) => ({
            ...prev,
            primaryKey: pkCandidate.column_name,
          }));
        }
      }
    } catch (error) {
      console.error("컬럼 목록 조회 실패:", error);
    } finally {
      setLoadingColumns(false);
    }
  };

  const usedColumns = useMemo(() => {
    const used = new Set<string>();
    config.rows.forEach((row) => {
      row.elements.forEach((el) => {
        if (el.type === "dataCell" && (el as CardDataCellElement).columnName) {
          used.add((el as CardDataCellElement).columnName!);
        }
        if (el.type === "badge" && (el as CardBadgeElement).columnName) {
          used.add((el as CardBadgeElement).columnName!);
        }
      });
    });
    return used;
  }, [config.rows]);

  const handleTableChange = (tableName: string) => {
    setConfig((prev) => ({
      ...prev,
      tableName,
      primaryKey: "",
      rows: prev.rows.map((row) => ({
        ...row,
        elements: row.elements.map((el) => {
          if (el.type === "dataCell") {
            return { ...el, columnName: undefined } as CardDataCellElement;
          }
          if (el.type === "badge") {
            return { ...el, columnName: undefined } as CardBadgeElement;
          }
          return el;
        }),
      })),
    }));
  };

  const handleRowsChange = (rows: CardLayoutRow[]) => {
    setConfig((prev) => ({ ...prev, rows }));
  };

  const handleColumnMapping = (
    rowIndex: number,
    elementIndex: number,
    columnName: string,
  ) => {
    setConfig((prev) => {
      const newRows = [...prev.rows];
      const newElements = [...newRows[rowIndex].elements];
      const element = newElements[elementIndex];
      if (element.type === "dataCell") {
        newElements[elementIndex] = {
          ...element,
          columnName,
        } as CardDataCellElement;
      } else if (element.type === "badge") {
        newElements[elementIndex] = {
          ...element,
          columnName,
        } as CardBadgeElement;
      }
      newRows[rowIndex] = { ...newRows[rowIndex], elements: newElements };
      return { ...prev, rows: newRows };
    });
  };

  const handleSave = () => {
    onSave(config);
    onOpenChange(false);
  };

  const renderLayoutTab = () => (
    <div className="space-y-4">
      <CardElementPalette />
      <CardCanvasEditor rows={config.rows} onRowsChange={handleRowsChange} />
    </div>
  );

  const renderBindingTab = () => (
    <div className="space-y-4">
      <div className="bg-teal-50 border border-teal-200 rounded-xl p-4 space-y-3">
        <div className="space-y-2">
          <Label className="text-xs font-medium text-foreground">
            테이블 선택
          </Label>
          <Select
            value={config.tableName || ""}
            onValueChange={handleTableChange}
            disabled={loadingTables}
          >
            <SelectTrigger className="h-9 text-sm">
              <SelectValue
                placeholder={loadingTables ? "로딩 중..." : "테이블을 선택하세요"}
              />
            </SelectTrigger>
            <SelectContent>
              {tables.map((table) => (
                <SelectItem key={table.table_name} value={table.table_name}>
                  {table.table_name}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>

        <div className="space-y-2">
          <Label className="text-xs font-medium text-muted-foreground">
            기본 키
          </Label>
          <Select
            value={config.primaryKey || ""}
            onValueChange={(pk) => setConfig((prev) => ({ ...prev, primaryKey: pk }))}
            disabled={!config.tableName || loadingColumns}
          >
            <SelectTrigger className="h-9 text-sm bg-muted">
              <SelectValue placeholder="기본 키 선택" />
            </SelectTrigger>
            <SelectContent>
              {columns.map((col) => (
                <SelectItem key={col.column_name} value={col.column_name}>
                  {col.column_name}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
      </div>

      <div className="bg-white border border-border rounded-xl overflow-hidden shadow-sm">
        <div
          className="p-3"
          style={{
            backgroundColor: config.backgroundColor,
            display: "flex",
            flexDirection: "column",
            gap: config.gap,
          }}
        >
          {config.rows.map((row, rowIndex) => (
            <div
              key={row.id}
              className="grid"
              style={{
                gridTemplateColumns: `repeat(${row.gridColumns}, 1fr)`,
                gap: config.gap,
              }}
            >
              {row.elements.map((element, elementIndex) => {
                const needsBinding =
                  element.type === "dataCell" || element.type === "badge";
                const currentColumn =
                  element.type === "dataCell"
                    ? (element as CardDataCellElement).columnName
                    : element.type === "badge"
                      ? (element as CardBadgeElement).columnName
                      : undefined;

                return (
                  <div
                    key={element.id}
                    className="border border-gray-100 rounded px-2 py-1.5 hover:bg-gray-50"
                    style={{ gridColumn: `span ${element.colspan || 1}` }}
                  >
                    <div className="flex items-center gap-1 mb-1">
                      <span className="text-gray-400">
                        {getElementIcon(element.type)}
                      </span>
                      <span className="text-xs text-muted-foreground">
                        {element.type === "header" && (element as any).title}
                        {element.type === "dataCell" &&
                          (element as CardDataCellElement).label}
                        {element.type === "divider" && "구분선"}
                        {element.type === "badge" &&
                          ((element as CardBadgeElement).label || "뱃지")}
                      </span>
                    </div>

                    {needsBinding && (
                      <Select
                        value={currentColumn || ""}
                        onValueChange={(col) =>
                          handleColumnMapping(rowIndex, elementIndex, col)
                        }
                        disabled={!config.tableName}
                      >
                        <SelectTrigger
                          className={`h-7 text-xs ${
                            currentColumn
                              ? "bg-blue-50 text-blue-700 border-blue-200"
                              : "border-dashed"
                          }`}
                        >
                          <SelectValue placeholder="컬럼 선택" />
                        </SelectTrigger>
                        <SelectContent>
                          {columns.map((col) => {
                            const isUsed =
                              usedColumns.has(col.column_name) &&
                              currentColumn !== col.column_name;
                            return (
                              <SelectItem
                                key={col.column_name}
                                value={col.column_name}
                                disabled={isUsed}
                                className={isUsed ? "opacity-50" : ""}
                              >
                                {col.column_name}
                                {isUsed && " (사용 중)"}
                              </SelectItem>
                            );
                          })}
                        </SelectContent>
                      </Select>
                    )}
                  </div>
                );
              })}
            </div>
          ))}
        </div>
      </div>

      {!config.tableName && (
        <div className="text-center text-sm text-muted-foreground py-4">
          테이블을 먼저 선택해주세요.
        </div>
      )}

      {config.tableName && config.rows.every((r) => r.elements.length === 0) && (
        <div className="text-center text-sm text-muted-foreground py-4">
          레이아웃 탭에서 요소를 먼저 추가해주세요.
        </div>
      )}
    </div>
  );

  const renderStyleTab = () => (
    <div className="space-y-4">
      <div className="bg-white border border-border rounded-xl p-4 space-y-3">
        <div className="text-xs font-medium text-foreground mb-2">카드 스타일</div>
        <div className="grid grid-cols-2 gap-3">
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">패딩</Label>
            <Select value={config.padding || "12px"} onValueChange={(v) => setConfig((prev) => ({ ...prev, padding: v }))}>
              <SelectTrigger className="h-9 text-sm"><SelectValue /></SelectTrigger>
              <SelectContent>
                <SelectItem value="8px">8px</SelectItem>
                <SelectItem value="12px">12px</SelectItem>
                <SelectItem value="16px">16px</SelectItem>
                <SelectItem value="20px">20px</SelectItem>
              </SelectContent>
            </Select>
          </div>
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">행 간격</Label>
            <Select value={config.gap || "8px"} onValueChange={(v) => setConfig((prev) => ({ ...prev, gap: v }))}>
              <SelectTrigger className="h-9 text-sm"><SelectValue /></SelectTrigger>
              <SelectContent>
                <SelectItem value="4px">4px</SelectItem>
                <SelectItem value="8px">8px</SelectItem>
                <SelectItem value="12px">12px</SelectItem>
                <SelectItem value="16px">16px</SelectItem>
              </SelectContent>
            </Select>
          </div>
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">테두리</Label>
            <Select value={config.borderStyle || "solid"} onValueChange={(v) => setConfig((prev) => ({ ...prev, borderStyle: v }))}>
              <SelectTrigger className="h-9 text-sm"><SelectValue /></SelectTrigger>
              <SelectContent>
                <SelectItem value="solid">실선</SelectItem>
                <SelectItem value="dashed">점선</SelectItem>
                <SelectItem value="none">없음</SelectItem>
              </SelectContent>
            </Select>
          </div>
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">테두리 색상</Label>
            <Input type="color" value={config.borderColor || "#e5e7eb"} onChange={(e) => setConfig((prev) => ({ ...prev, borderColor: e.target.value }))} className="h-9 w-full p-1" />
          </div>
          <div className="space-y-2 col-span-2">
            <Label className="text-xs font-medium text-foreground">배경색</Label>
            <Input type="color" value={config.backgroundColor || "#ffffff"} onChange={(e) => setConfig((prev) => ({ ...prev, backgroundColor: e.target.value }))} className="h-9 w-full p-1" />
          </div>
        </div>
      </div>
      <div className="bg-white border border-border rounded-xl p-4 space-y-3">
        <div className="text-xs font-medium text-foreground mb-2">요소별 스타일</div>
        <div className="grid grid-cols-2 gap-3">
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">헤더 폰트 크기</Label>
            <Input type="number" min={10} max={24} value={config.headerTitleFontSize || 14} onChange={(e) => setConfig((prev) => ({ ...prev, headerTitleFontSize: parseInt(e.target.value) || 14 }))} className="h-9 text-sm" />
          </div>
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">헤더 색상</Label>
            <Input type="color" value={config.headerTitleColor || "#1e40af"} onChange={(e) => setConfig((prev) => ({ ...prev, headerTitleColor: e.target.value }))} className="h-9 w-full p-1" />
          </div>
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">라벨 폰트 크기</Label>
            <Input type="number" min={10} max={20} value={config.labelFontSize || 13} onChange={(e) => setConfig((prev) => ({ ...prev, labelFontSize: parseInt(e.target.value) || 13 }))} className="h-9 text-sm" />
          </div>
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">라벨 색상</Label>
            <Input type="color" value={config.labelColor || "#374151"} onChange={(e) => setConfig((prev) => ({ ...prev, labelColor: e.target.value }))} className="h-9 w-full p-1" />
          </div>
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">값 폰트 크기</Label>
            <Input type="number" min={10} max={20} value={config.valueFontSize || 13} onChange={(e) => setConfig((prev) => ({ ...prev, valueFontSize: parseInt(e.target.value) || 13 }))} className="h-9 text-sm" />
          </div>
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">값 색상</Label>
            <Input type="color" value={config.valueColor || "#000000"} onChange={(e) => setConfig((prev) => ({ ...prev, valueColor: e.target.value }))} className="h-9 w-full p-1" />
          </div>
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">구분선 두께</Label>
            <Input type="number" min={1} max={5} value={config.dividerThickness || 1} onChange={(e) => setConfig((prev) => ({ ...prev, dividerThickness: parseInt(e.target.value) || 1 }))} className="h-9 text-sm" />
          </div>
          <div className="space-y-2">
            <Label className="text-xs font-medium text-foreground">구분선 색상</Label>
            <Input type="color" value={config.dividerColor || "#e5e7eb"} onChange={(e) => setConfig((prev) => ({ ...prev, dividerColor: e.target.value }))} className="h-9 w-full p-1" />
          </div>
        </div>
      </div>
    </div>
  );

  return (
    <>
      <Dialog open={open} onOpenChange={guard.handleOpenChange}>
        <DialogContent className="max-w-4xl h-[92vh] overflow-hidden flex flex-col p-0 [&>button]:hidden">
          <DialogTitle className="sr-only">카드 레이아웃 설정</DialogTitle>
          <DialogDescription className="sr-only">
            카드 컴포넌트의 레이아웃, 데이터 바인딩, 스타일을 설정합니다
          </DialogDescription>

          {/* Header */}
          <div className="px-6 py-4 border-b border-border flex items-center justify-between">
            <div className="flex items-center gap-2">
              <LayoutGrid className="w-4 h-4 text-blue-600" />
              <h2 className="text-base font-semibold text-foreground">
                카드 레이아웃 설정
              </h2>
            </div>
            <Button
              variant="ghost"
              size="icon"
            onClick={guard.tryClose}
            className="w-8 h-8"
            >
              <X className="w-4 h-4" />
            </Button>
          </div>

          {/* Tab */}
          <div className="mx-6 mt-3">
            <div className="h-9 bg-muted/30 rounded-lg p-0.5 inline-flex">
              <button
                onClick={() => setActiveTab("layout")}
                className={`px-3 py-1.5 rounded-md text-xs font-medium transition-all flex items-center gap-1.5 ${
                  activeTab === "layout"
                    ? "bg-blue-50 text-blue-700 shadow-sm"
                    : "bg-transparent text-foreground hover:text-foreground/80"
                }`}
              >
                <LayoutGrid className="w-3.5 h-3.5" />
                레이아웃
              </button>
              <button
                onClick={() => setActiveTab("binding")}
                className={`px-3 py-1.5 rounded-md text-xs font-medium transition-all flex items-center gap-1.5 ${
                  activeTab === "binding"
                    ? "bg-blue-50 text-blue-700 shadow-sm"
                    : "bg-transparent text-foreground hover:text-foreground/80"
                }`}
              >
                <Database className="w-3.5 h-3.5" />
                데이터 바인딩
              </button>
              <button
                onClick={() => setActiveTab("style")}
                className={`px-3 py-1.5 rounded-md text-xs font-medium transition-all flex items-center gap-1.5 ${
                  activeTab === "style"
                    ? "bg-blue-50 text-blue-700 shadow-sm"
                    : "bg-transparent text-foreground hover:text-foreground/80"
                }`}
              >
                <Palette className="w-3.5 h-3.5" />
                스타일
              </button>
            </div>
          </div>

          {/* Content */}
          <div className="flex-1 overflow-y-auto px-6 py-4">
            {activeTab === "layout" && renderLayoutTab()}
            {activeTab === "binding" && renderBindingTab()}
            {activeTab === "style" && renderStyleTab()}
          </div>

          {/* Footer */}
          <div className="px-6 py-4 border-t border-border flex items-center justify-end gap-2">
            <Button variant="outline" onClick={guard.tryClose}>
              취소
            </Button>
            <Button className="bg-blue-600 hover:bg-blue-700" onClick={handleSave}>
              저장
            </Button>
          </div>
        </DialogContent>
      </Dialog>

      <UnsavedChangesDialog guard={guard} />
    </>
  );
}
