"use client";

/**
 * DataGridChartPanel — DataGrid 하단 차트 분석 패널.
 *
 * 기능:
 * - 여러 차트 동시 관리 (추가/삭제/제목 편집/드래그 순서 변경)
 * - 차트 타입: Bar / Line / Pie
 * - X축 컬럼 선택 (모든 컬럼)
 * - Y축 컬럼 선택 (숫자 컬럼)
 * - 집계: count / sum / avg / min / max
 * - localStorage 영속 (gridId 기준)
 */

import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
  BarChart, Bar, LineChart, Line, PieChart, Pie, Cell,
  XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer,
} from "recharts";
import {
  DndContext, closestCenter, PointerSensor, useSensor, useSensors, type DragEndEvent,
} from "@dnd-kit/core";
import { SortableContext, useSortable, arrayMove, verticalListSortingStrategy } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { Plus, X, Pencil, ChevronDown, ChevronUp, GripVertical } from "lucide-react";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Input } from "@/components/ui/input";
import { cn } from "@/lib/utils";
import type { DataGridColumn } from "./DataGrid";

type AggType = "count" | "sum" | "avg" | "min" | "max";
type ChartType = "bar" | "line" | "pie";

interface ChartConfig {
  id: string;
  title: string;
  type: ChartType;
  xKey: string;
  yKey: string;
  agg: AggType;
}

const AGG_LABEL: Record<AggType, string> = {
  count: "건수", sum: "합계", avg: "평균", min: "최소", max: "최대",
};
const CHART_TYPE_LABEL: Record<ChartType, string> = {
  bar: "막대", line: "선", pie: "원형",
};
const PIE_COLORS = ["#3b82f6", "#f59e0b", "#10b981", "#ef4444", "#8b5cf6", "#ec4899", "#06b6d4", "#84cc16"];

function newChartConfig(columns: DataGridColumn[]): ChartConfig {
  const numericCols = columns.filter((c) => c.formatNumber || c.formatMoney || c.inputType === "number");
  const firstCat = columns.find((c) => !numericCols.includes(c));
  const firstNum = numericCols[0];
  return {
    id: `chart-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
    title: "제목 없는 차트",
    type: "bar",
    xKey: firstCat?.key ?? columns[0]?.key ?? "",
    yKey: firstNum?.key ?? "",
    agg: firstNum ? "sum" : "count",
  };
}

function aggregate(
  rows: Record<string, any>[],
  xKey: string,
  yKey: string,
  agg: AggType,
): Array<{ name: string; value: number }> {
  const groups: Record<string, number[]> = {};
  for (const row of rows) {
    const xVal = row[xKey] == null || row[xKey] === "" ? "(빈 값)" : String(row[xKey]);
    if (!groups[xVal]) groups[xVal] = [];
    if (agg === "count") {
      groups[xVal].push(1);
    } else {
      const raw = row[yKey];
      const n = typeof raw === "number" ? raw : Number(String(raw ?? "").replace(/,/g, ""));
      if (!isNaN(n)) groups[xVal].push(n);
    }
  }
  return Object.entries(groups).map(([name, vals]) => {
    let v: number;
    if (agg === "count") v = vals.length;
    else if (agg === "sum") v = vals.reduce((a, b) => a + b, 0);
    else if (agg === "avg") v = vals.length > 0 ? vals.reduce((a, b) => a + b, 0) / vals.length : 0;
    else if (agg === "min") v = vals.length > 0 ? Math.min(...vals) : 0;
    else v = vals.length > 0 ? Math.max(...vals) : 0;
    return { name, value: Number(v.toFixed(2)) };
  });
}

// ─── 단일 차트 카드 ─────────────────────────────────────────────

interface ChartCardProps {
  cfg: ChartConfig;
  columns: DataGridColumn[];
  data: Record<string, any>[];
  onChange: (next: ChartConfig) => void;
  onDelete: () => void;
}

function SortableChartCard({ cfg, columns, data, onChange, onDelete }: ChartCardProps) {
  const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: cfg.id });
  const [editingTitle, setEditingTitle] = useState(false);
  const [titleDraft, setTitleDraft] = useState(cfg.title);

  const numericCols = useMemo(
    () => columns.filter((c) => c.formatNumber || c.formatMoney || c.inputType === "number"),
    [columns],
  );

  const chartData = useMemo(
    () => aggregate(data, cfg.xKey, cfg.yKey, cfg.agg),
    [data, cfg.xKey, cfg.yKey, cfg.agg],
  );

  const style: React.CSSProperties = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
  };

  return (
    <div
      ref={setNodeRef}
      style={style}
      className="rounded-md border bg-card text-card-foreground shadow-sm"
    >
      {/* 카드 헤더: 드래그 핸들 + 제목 + 삭제 */}
      <div className="flex items-center gap-2 border-b px-3 py-2">
        <button
          {...attributes}
          {...listeners}
          className="cursor-grab active:cursor-grabbing text-muted-foreground"
          title="드래그하여 순서 변경"
          type="button"
        >
          <GripVertical className="h-4 w-4" />
        </button>
        {editingTitle ? (
          <Input
            value={titleDraft}
            autoFocus
            onChange={(e) => setTitleDraft(e.target.value)}
            onBlur={() => { onChange({ ...cfg, title: titleDraft.trim() || "제목 없는 차트" }); setEditingTitle(false); }}
            onKeyDown={(e) => {
              if (e.key === "Enter") { onChange({ ...cfg, title: titleDraft.trim() || "제목 없는 차트" }); setEditingTitle(false); }
              if (e.key === "Escape") { setTitleDraft(cfg.title); setEditingTitle(false); }
            }}
            className="h-7 text-sm flex-1"
          />
        ) : (
          <button
            type="button"
            onClick={() => { setTitleDraft(cfg.title); setEditingTitle(true); }}
            className="text-sm font-medium hover:underline flex-1 text-left truncate"
            title="클릭하여 제목 편집"
          >
            {cfg.title}
            <Pencil className="inline ml-1.5 h-3 w-3 text-muted-foreground/60" />
          </button>
        )}
        <button
          type="button"
          onClick={onDelete}
          className="h-7 w-7 inline-flex items-center justify-center rounded hover:bg-muted text-muted-foreground"
          title="차트 삭제"
        >
          <X className="h-4 w-4" />
        </button>
      </div>

      {/* 컨트롤 행 */}
      <div className="flex flex-wrap items-center gap-2 px-3 py-2 border-b bg-muted/20 text-xs">
        <span className="text-muted-foreground">유형</span>
        <Select value={cfg.type} onValueChange={(v) => onChange({ ...cfg, type: v as ChartType })}>
          <SelectTrigger className="h-7 w-[80px] text-xs"><SelectValue /></SelectTrigger>
          <SelectContent>
            {(["bar", "line", "pie"] as ChartType[]).map((t) => (
              <SelectItem key={t} value={t} className="text-xs">{CHART_TYPE_LABEL[t]}</SelectItem>
            ))}
          </SelectContent>
        </Select>

        <span className="text-muted-foreground ml-2">X축</span>
        <Select value={cfg.xKey} onValueChange={(v) => onChange({ ...cfg, xKey: v })}>
          <SelectTrigger className="h-7 w-[140px] text-xs"><SelectValue /></SelectTrigger>
          <SelectContent>
            {columns.map((c) => (
              <SelectItem key={c.key} value={c.key} className="text-xs">{c.label}</SelectItem>
            ))}
          </SelectContent>
        </Select>

        <span className="text-muted-foreground ml-2">집계</span>
        <Select value={cfg.agg} onValueChange={(v) => onChange({ ...cfg, agg: v as AggType })}>
          <SelectTrigger className="h-7 w-[80px] text-xs"><SelectValue /></SelectTrigger>
          <SelectContent>
            {(["count", "sum", "avg", "min", "max"] as AggType[]).map((a) => (
              <SelectItem key={a} value={a} className="text-xs">{AGG_LABEL[a]}</SelectItem>
            ))}
          </SelectContent>
        </Select>

        {cfg.agg !== "count" && (
          <>
            <span className="text-muted-foreground ml-2">Y축</span>
            <Select value={cfg.yKey} onValueChange={(v) => onChange({ ...cfg, yKey: v })}>
              <SelectTrigger className="h-7 w-[140px] text-xs"><SelectValue placeholder="숫자 컬럼 선택" /></SelectTrigger>
              <SelectContent>
                {numericCols.length === 0 ? (
                  <div className="px-2 py-1 text-xs text-muted-foreground">숫자 컬럼 없음</div>
                ) : numericCols.map((c) => (
                  <SelectItem key={c.key} value={c.key} className="text-xs">{c.label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          </>
        )}
      </div>

      {/* 차트 본체 */}
      <div className="p-3">
        {chartData.length === 0 ? (
          <div className="h-[240px] flex items-center justify-center text-muted-foreground text-xs">
            데이터 없음
          </div>
        ) : (
          <ResponsiveContainer width="100%" height={240}>
            {cfg.type === "bar" ? (
              <BarChart data={chartData}>
                <CartesianGrid strokeDasharray="3 3" stroke="hsl(var(--border))" />
                <XAxis dataKey="name" tick={{ fontSize: 11 }} />
                <YAxis tick={{ fontSize: 11 }} />
                <Tooltip />
                <Bar dataKey="value" fill="#3b82f6" name={`${columns.find((c) => c.key === cfg.yKey)?.label ?? ""} ${AGG_LABEL[cfg.agg]}`} />
              </BarChart>
            ) : cfg.type === "line" ? (
              <LineChart data={chartData}>
                <CartesianGrid strokeDasharray="3 3" stroke="hsl(var(--border))" />
                <XAxis dataKey="name" tick={{ fontSize: 11 }} />
                <YAxis tick={{ fontSize: 11 }} />
                <Tooltip />
                <Line type="monotone" dataKey="value" stroke="#3b82f6" strokeWidth={2} name={`${columns.find((c) => c.key === cfg.yKey)?.label ?? ""} ${AGG_LABEL[cfg.agg]}`} />
              </LineChart>
            ) : (
              <PieChart>
                <Pie data={chartData} dataKey="value" nameKey="name" cx="50%" cy="50%" outerRadius={80} label={{ fontSize: 11 }}>
                  {chartData.map((_, idx) => <Cell key={idx} fill={PIE_COLORS[idx % PIE_COLORS.length]} />)}
                </Pie>
                <Tooltip />
                <Legend wrapperStyle={{ fontSize: 11 }} />
              </PieChart>
            )}
          </ResponsiveContainer>
        )}
      </div>
    </div>
  );
}

// ─── 패널 본체 ──────────────────────────────────────────────────

interface DataGridChartPanelProps {
  /** localStorage 키 prefix용 grid ID. 미지정 시 영속 비활성 */
  gridId?: string;
  columns: DataGridColumn[];
  data: Record<string, any>[];
}

export function DataGridChartPanel({ gridId, columns, data }: DataGridChartPanelProps) {
  const [charts, setCharts] = useState<ChartConfig[]>([]);
  const [collapsed, setCollapsed] = useState(false);

  const storageKey = gridId ? `datagrid_charts_${gridId}` : null;

  // 영속 로드
  useEffect(() => {
    if (!storageKey) return;
    try {
      const saved = localStorage.getItem(storageKey);
      if (saved) {
        const parsed = JSON.parse(saved) as ChartConfig[];
        if (Array.isArray(parsed)) setCharts(parsed);
      }
    } catch { /* skip */ }
  }, [storageKey]);

  const persist = useCallback((next: ChartConfig[]) => {
    setCharts(next);
    if (storageKey) {
      try { localStorage.setItem(storageKey, JSON.stringify(next)); } catch { /* skip */ }
    }
  }, [storageKey]);

  const addChart = () => persist([...charts, newChartConfig(columns)]);
  const updateChart = (id: string, next: ChartConfig) => persist(charts.map((c) => c.id === id ? next : c));
  const deleteChart = (id: string) => persist(charts.filter((c) => c.id !== id));

  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 8 } }));
  const handleDragEnd = (e: DragEndEvent) => {
    const { active, over } = e;
    if (!over || active.id === over.id) return;
    const oldIdx = charts.findIndex((c) => c.id === active.id);
    const newIdx = charts.findIndex((c) => c.id === over.id);
    if (oldIdx < 0 || newIdx < 0) return;
    persist(arrayMove(charts, oldIdx, newIdx));
  };

  return (
    <div className={cn("border-t bg-muted/10 flex flex-col shrink-0", collapsed ? "" : "h-[360px]")}>
      {/* 패널 헤더 */}
      <div className="flex items-center justify-between px-3 py-2 border-b shrink-0">
        <div className="flex items-center gap-2">
          <button
            type="button"
            onClick={() => setCollapsed((p) => !p)}
            className="h-6 w-6 inline-flex items-center justify-center rounded hover:bg-muted text-muted-foreground"
            title={collapsed ? "펼치기" : "접기"}
          >
            {collapsed ? <ChevronDown className="h-4 w-4" /> : <ChevronUp className="h-4 w-4" />}
          </button>
          <span className="text-sm font-semibold">차트 분석 ({charts.length}개)</span>
        </div>
        <button
          type="button"
          onClick={addChart}
          className="h-7 inline-flex items-center gap-1 px-2 rounded hover:bg-muted text-muted-foreground text-xs"
          title="차트 추가"
        >
          <Plus className="h-3.5 w-3.5" /> 차트 추가
        </button>
      </div>

      {/* 차트 카드들 — 내부 스크롤 */}
      {!collapsed && (
        <div className="flex-1 min-h-0 overflow-y-auto p-3">
          {charts.length === 0 ? (
            <div className="py-8 text-center text-muted-foreground text-xs">
              + 차트 추가 버튼을 눌러 분석 차트를 만들어보세요.
            </div>
          ) : (
            <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
              <SortableContext items={charts.map((c) => c.id)} strategy={verticalListSortingStrategy}>
                <div className={cn("grid gap-3", charts.length >= 2 ? "grid-cols-1 lg:grid-cols-2" : "grid-cols-1")}>
                  {charts.map((cfg) => (
                    <SortableChartCard
                      key={cfg.id}
                      cfg={cfg}
                      columns={columns}
                      data={data}
                      onChange={(next) => updateChart(cfg.id, next)}
                      onDelete={() => deleteChart(cfg.id)}
                    />
                  ))}
                </div>
              </SortableContext>
            </DndContext>
          )}
        </div>
      )}
    </div>
  );
}
