"use client";

import { useState, useEffect, useCallback, useMemo } from "react";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Database, Columns3, FunctionSquare, Play, Plus, Trash2, Code, Loader2 } from "lucide-react";
import { reportApi } from "@/lib/api/reportApi";
import { useReportDesigner } from "@/contexts/ReportDesignerContext";
import type { ComponentConfig, VisualQuery, VisualQueryFormulaColumn } from "@/types/report";

// ─── 타입 ──────────────────────────────────────────────────────────────────────

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

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

interface Props {
  component: ComponentConfig;
}

// ─── 컴포넌트 ──────────────────────────────────────────────────────────────────

export function VisualQueryBuilder({ component }: Props) {
  const { updateComponent, setQueryResult } = useReportDesigner();

  const vq: VisualQuery = component.visualQuery ?? {
    tableName: "",
    limit: 100,
    columns: [],
    formulaColumns: [],
  };

  // ─── 스키마 상태 ───────────────────────────────────────────────────────────────

  const [tables, setTables] = useState<SchemaTable[]>([]);
  const [columns, setColumns] = useState<SchemaColumn[]>([]);
  const [tablesLoading, setTablesLoading] = useState(false);
  const [columnsLoading, setColumnsLoading] = useState(false);
  const [previewLoading, setPreviewLoading] = useState(false);
  const [generatedSql, setGeneratedSql] = useState("");
  const [previewError, setPreviewError] = useState("");

  // ─── 테이블 목록 로드 ──────────────────────────────────────────────────────────

  useEffect(() => {
    let cancelled = false;
    const loadTables = async () => {
      setTablesLoading(true);
      try {
        const res = await reportApi.getSchemaTableList();
        if (!cancelled && res.success) setTables(res.data);
      } catch {
        /* 무시 */
      } finally {
        if (!cancelled) setTablesLoading(false);
      }
    };
    loadTables();
    return () => { cancelled = true; };
  }, []);

  // ─── 테이블 변경 시 컬럼 로드 ──────────────────────────────────────────────────

  useEffect(() => {
    if (!vq.tableName) {
      setColumns([]);
      return;
    }
    let cancelled = false;
    const loadColumns = async () => {
      setColumnsLoading(true);
      try {
        const res = await reportApi.getSchemaTableColumns(vq.tableName);
        if (!cancelled && res.success) setColumns(res.data);
      } catch {
        /* 무시 */
      } finally {
        if (!cancelled) setColumnsLoading(false);
      }
    };
    loadColumns();
    return () => { cancelled = true; };
  }, [vq.tableName]);

  // ─── visualQuery 업데이트 헬퍼 ────────────────────────────────────────────────

  const updateVQ = useCallback(
    (patch: Partial<VisualQuery>) => {
      updateComponent(component.id, { visualQuery: { ...vq, ...patch } });
    },
    [component.id, vq, updateComponent],
  );

  // ─── 테이블 선택 ───────────────────────────────────────────────────────────────

  const handleTableChange = useCallback(
    (tableName: string) => {
      updateComponent(component.id, {
        visualQuery: {
          tableName: tableName === "none" ? "" : tableName,
          limit: vq.limit ?? 100,
          columns: [],
          formulaColumns: [],
        },
      });
    },
    [component.id, vq.limit, updateComponent],
  );

  // ─── 컬럼 토글 ─────────────────────────────────────────────────────────────────

  const toggleColumn = useCallback(
    (colName: string) => {
      const selected = vq.columns.includes(colName)
        ? vq.columns.filter((c) => c !== colName)
        : [...vq.columns, colName];
      updateVQ({ columns: selected });
    },
    [vq.columns, updateVQ],
  );

  const selectAllColumns = useCallback(() => {
    updateVQ({ columns: columns.map((c) => c.column_name) });
  }, [columns, updateVQ]);

  const deselectAllColumns = useCallback(() => {
    updateVQ({ columns: [] });
  }, [updateVQ]);

  // ─── 수식 컬럼 관리 ────────────────────────────────────────────────────────────

  const addFormulaColumn = useCallback(() => {
    const fc: VisualQueryFormulaColumn = {
      alias: `calc_${(vq.formulaColumns.length + 1)}`,
      header: `수식 ${vq.formulaColumns.length + 1}`,
      expression: "",
    };
    updateVQ({ formulaColumns: [...vq.formulaColumns, fc] });
  }, [vq.formulaColumns, updateVQ]);

  const updateFormulaColumn = useCallback(
    (idx: number, patch: Partial<VisualQueryFormulaColumn>) => {
      const updated = vq.formulaColumns.map((fc, i) => (i === idx ? { ...fc, ...patch } : fc));
      updateVQ({ formulaColumns: updated });
    },
    [vq.formulaColumns, updateVQ],
  );

  const removeFormulaColumn = useCallback(
    (idx: number) => {
      updateVQ({ formulaColumns: vq.formulaColumns.filter((_, i) => i !== idx) });
    },
    [vq.formulaColumns, updateVQ],
  );

  // ─── SQL 미리보기 빌드 ────────────────────────────────────────────────────────

  const previewSql = useMemo(() => {
    if (!vq.tableName || (vq.columns.length === 0 && vq.formulaColumns.length === 0)) return "";
    const parts: string[] = [];
    for (const col of vq.columns) parts.push(`"${col}"`);
    for (const fc of vq.formulaColumns) {
      if (fc.expression && fc.alias) parts.push(`(${fc.expression}) AS "${fc.alias}"`);
    }
    if (parts.length === 0) return "";
    const limit = Math.min(Math.max(vq.limit ?? 100, 1), 10000);
    return `SELECT ${parts.join(", ")} FROM "${vq.tableName}" LIMIT ${limit}`;
  }, [vq]);

  // ─── 미리보기 실행 ────────────────────────────────────────────────────────────

  const resultKey = `visual_${component.id}`;

  const handlePreview = useCallback(async () => {
    if (!vq.tableName || (vq.columns.length === 0 && vq.formulaColumns.length === 0)) return;
    setPreviewLoading(true);
    setPreviewError("");
    try {
      const res = await reportApi.previewVisualQuery(vq);
      if (res.success) {
        setQueryResult(resultKey, res.data.fields, res.data.rows);
        setGeneratedSql(res.data.sql);
      } else {
        setPreviewError("쿼리 실행에 실패했습니다.");
      }
    } catch (err: any) {
      setPreviewError(err?.response?.data?.message || err.message || "오류가 발생했습니다.");
    } finally {
      setPreviewLoading(false);
    }
  }, [vq, resultKey, setQueryResult]);

  const hasSelection = vq.columns.length > 0 || vq.formulaColumns.length > 0;

  // ─── 렌더링 ────────────────────────────────────────────────────────────────────

  return (
    <div className="space-y-3">
      {/* [1] 데이터 소스 */}
      <Card className="border-blue-200 bg-blue-50">
        <CardHeader className="pb-2">
          <div className="flex items-center gap-2">
            <Database className="h-4 w-4 text-blue-600" />
            <CardTitle className="text-xs text-blue-900">데이터 소스</CardTitle>
          </div>
        </CardHeader>
        <CardContent className="space-y-2">
          <div>
            <Label className="text-xs">테이블</Label>
            <Select
              value={vq.tableName || "none"}
              onValueChange={handleTableChange}
              disabled={tablesLoading}
            >
              <SelectTrigger className="h-8 bg-white text-xs">
                <SelectValue placeholder={tablesLoading ? "로딩 중..." : "테이블 선택"} />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="none">선택 안함</SelectItem>
                {tables.map((t) => (
                  <SelectItem key={t.table_name} value={t.table_name}>
                    {t.table_name}
                    <span className="ml-1 text-[10px] text-gray-400">
                      {t.table_type === "VIEW" ? "(뷰)" : ""}
                    </span>
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <div>
            <Label className="text-xs">최대 행 수</Label>
            <Input
              type="number"
              min={1}
              max={10000}
              value={vq.limit ?? 100}
              onChange={(e) => updateVQ({ limit: parseInt(e.target.value) || 100 })}
              className="h-8 bg-white text-xs"
            />
          </div>
        </CardContent>
      </Card>

      {/* [2] 컬럼 선택 */}
      {vq.tableName && (
        <Card className="border-green-200 bg-green-50">
          <CardHeader className="flex flex-row items-center justify-between pb-2">
            <div className="flex items-center gap-2">
              <Columns3 className="h-4 w-4 text-green-600" />
              <CardTitle className="text-xs text-green-900">
                컬럼 선택
                {vq.columns.length > 0 && (
                  <span className="ml-1 font-normal text-green-600">
                    ({vq.columns.length}/{columns.length})
                  </span>
                )}
              </CardTitle>
            </div>
            <div className="flex gap-1">
              <Button
                size="sm"
                variant="ghost"
                className="h-6 px-2 text-[10px]"
                onClick={selectAllColumns}
              >
                전체 선택
              </Button>
              <Button
                size="sm"
                variant="ghost"
                className="h-6 px-2 text-[10px]"
                onClick={deselectAllColumns}
              >
                전체 해제
              </Button>
            </div>
          </CardHeader>
          <CardContent>
            {columnsLoading ? (
              <div className="flex items-center justify-center py-4">
                <Loader2 className="h-4 w-4 animate-spin text-green-600" />
                <span className="ml-2 text-xs text-green-700">컬럼 로딩 중...</span>
              </div>
            ) : columns.length > 0 ? (
              <div className="grid max-h-48 grid-cols-2 gap-1 overflow-y-auto">
                {columns.map((col) => {
                  const checked = vq.columns.includes(col.column_name);
                  return (
                    <label
                      key={col.column_name}
                      className={`flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 text-xs transition-colors ${
                        checked ? "bg-green-200/60 text-green-900" : "text-gray-600 hover:bg-green-100/40"
                      }`}
                    >
                      <input
                        type="checkbox"
                        checked={checked}
                        onChange={() => toggleColumn(col.column_name)}
                        className="h-3.5 w-3.5 rounded border-gray-300 text-green-600"
                      />
                      <span className="truncate font-mono">{col.column_name}</span>
                      <span className="ml-auto shrink-0 text-[9px] text-gray-400">
                        {col.data_type}
                      </span>
                    </label>
                  );
                })}
              </div>
            ) : (
              <p className="py-4 text-center text-xs text-gray-500">컬럼 정보가 없습니다.</p>
            )}
          </CardContent>
        </Card>
      )}

      {/* [3] 수식 컬럼 */}
      {vq.tableName && (
        <Card className="border-amber-200 bg-amber-50">
          <CardHeader className="flex flex-row items-center justify-between pb-2">
            <div className="flex items-center gap-2">
              <FunctionSquare className="h-4 w-4 text-amber-600" />
              <CardTitle className="text-xs text-amber-900">
                수식 컬럼
                {vq.formulaColumns.length > 0 && (
                  <span className="ml-1 font-normal text-amber-600">
                    ({vq.formulaColumns.length})
                  </span>
                )}
              </CardTitle>
            </div>
            <Button
              size="sm"
              variant="outline"
              className="h-6 bg-white px-2 text-[10px]"
              onClick={addFormulaColumn}
            >
              <Plus className="mr-1 h-3 w-3" />
              추가
            </Button>
          </CardHeader>
          <CardContent className="space-y-2">
            {vq.formulaColumns.length > 0 ? (
              vq.formulaColumns.map((fc, idx) => (
                <div
                  key={idx}
                  className="flex items-start gap-1 rounded border border-amber-200 bg-white p-2"
                >
                  <div className="flex flex-1 flex-col gap-1">
                    <div className="flex gap-1">
                      <Input
                        value={fc.alias}
                        onChange={(e) => updateFormulaColumn(idx, { alias: e.target.value })}
                        placeholder="필드명"
                        className="h-7 flex-1 font-mono text-xs"
                      />
                      <Input
                        value={fc.header}
                        onChange={(e) => updateFormulaColumn(idx, { header: e.target.value })}
                        placeholder="표시 헤더"
                        className="h-7 flex-1 text-xs"
                      />
                    </div>
                    <Input
                      value={fc.expression}
                      onChange={(e) => updateFormulaColumn(idx, { expression: e.target.value })}
                      placeholder='SQL 표현식 (예: "price" * "quantity")'
                      className="h-7 font-mono text-xs"
                    />
                  </div>
                  <Button
                    size="sm"
                    variant="ghost"
                    className="mt-0.5 h-6 w-6 shrink-0 p-0 text-gray-400 hover:text-red-500"
                    onClick={() => removeFormulaColumn(idx)}
                  >
                    <Trash2 className="h-3.5 w-3.5" />
                  </Button>
                </div>
              ))
            ) : (
              <p className="py-2 text-center text-[10px] text-gray-500">
                계산이 필요한 컬럼을 추가하세요. (예: price * quantity)
              </p>
            )}
          </CardContent>
        </Card>
      )}

      {/* [4] SQL 미리보기 + 실행 */}
      {vq.tableName && hasSelection && (
        <Card className="border-gray-200 bg-gray-50">
          <CardHeader className="flex flex-row items-center justify-between pb-2">
            <div className="flex items-center gap-2">
              <Code className="h-4 w-4 text-gray-600" />
              <CardTitle className="text-xs text-gray-700">생성 SQL</CardTitle>
            </div>
            <Button
              size="sm"
              variant="default"
              className="h-7 bg-blue-600 px-3 text-xs hover:bg-blue-700"
              onClick={handlePreview}
              disabled={previewLoading}
            >
              {previewLoading ? (
                <Loader2 className="mr-1 h-3 w-3 animate-spin" />
              ) : (
                <Play className="mr-1 h-3 w-3" />
              )}
              미리보기
            </Button>
          </CardHeader>
          <CardContent>
            <pre className="overflow-x-auto rounded bg-gray-900 p-2 font-mono text-[10px] leading-relaxed text-green-300">
              {generatedSql || previewSql || "컬럼을 선택하세요."}
            </pre>
            {previewError && (
              <p className="mt-2 text-xs text-red-600">{previewError}</p>
            )}
          </CardContent>
        </Card>
      )}
    </div>
  );
}
