"use client";

import { useEffect, useState } from "react";
import { Loader2, Plus, RefreshCw, Trash2 } from "lucide-react";
import { fetchLiveChartData, type ChartDataSource } from "@/lib/notes/live-chart-data";
import {
  Area,
  AreaChart,
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  Legend,
  Pie,
  PieChart,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import { NodeViewWrapper } from "@tiptap/react";
import type { NodeViewProps } from "@tiptap/react";
import { cn } from "@/lib/utils";

export type ChartType = "bar" | "line" | "pie";
export interface ChartPoint {
  label: string;
  value: number;
}

// Shades of the same Mindavio sky-blue accent rather than a rainbow —
// a pie chart still needs distinguishable slices, but stays on-brand.
const PIE_COLORS = ["#7dd3fc", "#38bdf8", "#0ea5e9", "#0284c7", "#0369a1", "#075985"];
const CHART_TYPES: { id: ChartType; label: string }[] = [
  { id: "bar", label: "Bar" },
  { id: "line", label: "Line" },
  { id: "pie", label: "Pie" },
];

function formatValue(value: number) {
  return new Intl.NumberFormat("de-DE").format(value);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function ChartTooltip({ active, payload, label }: any) {
  if (!active || !payload?.length) return null;
  const point = payload[0];
  return (
    <div className="rounded-lg border border-border bg-popover px-3 py-2 text-[12px] shadow-xl">
      <p className="font-medium text-foreground">{point.name ?? label}</p>
      <p className="text-muted-foreground">{formatValue(point.value as number)}</p>
    </div>
  );
}

export function ChartBlockView({ node, updateAttributes, editor }: NodeViewProps) {
  const chartType = node.attrs.chartType as ChartType;
  const storedData = node.attrs.data as ChartPoint[];
  const dataSource = node.attrs.dataSource as ChartDataSource | null;
  const title = (node.attrs.title as string) || "";
  const editable = editor.isEditable;

  const [liveData, setLiveData] = useState<ChartPoint[] | null>(null);
  const [liveLoading, setLiveLoading] = useState(!!dataSource);

  useEffect(() => {
    if (!dataSource) return;
    let cancelled = false;
    setLiveLoading(true);
    void fetchLiveChartData(dataSource).then((points) => {
      if (!cancelled) {
        setLiveData(points);
        setLiveLoading(false);
      }
    });
    return () => {
      cancelled = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [dataSource?.type, dataSource?.days]);

  const data = dataSource ? liveData || [] : storedData;
  const total = data.reduce((sum, point) => sum + point.value, 0);

  function updatePoint(index: number, patch: Partial<ChartPoint>) {
    updateAttributes({ data: data.map((point, i) => (i === index ? { ...point, ...patch } : point)) });
  }

  function addPoint() {
    updateAttributes({ data: [...data, { label: `Item ${data.length + 1}`, value: 0 }] });
  }

  function removePoint(index: number) {
    updateAttributes({ data: data.filter((_, i) => i !== index) });
  }

  return (
    <NodeViewWrapper className="my-3">
      <div className="rounded-2xl border border-border bg-card/60 p-4" contentEditable={false}>
        <div className="mb-3 flex flex-wrap items-center justify-between gap-2">
          {editable ? (
            <input
              value={title}
              onChange={(e) => updateAttributes({ title: e.target.value })}
              placeholder="Untitled chart"
              className="min-w-0 flex-1 bg-transparent text-[13px] font-semibold text-foreground outline-none placeholder:text-muted-foreground/50"
            />
          ) : (
            <p className="text-[13px] font-semibold text-foreground">{title || "Untitled chart"}</p>
          )}

          <div className="flex items-center gap-2">
            {dataSource && (
              <button
                type="button"
                onClick={() => {
                  setLiveLoading(true);
                  void fetchLiveChartData(dataSource).then((points) => {
                    setLiveData(points);
                    setLiveLoading(false);
                  });
                }}
                title="Refresh live data"
                className="flex items-center gap-1 rounded-full border border-sky-500/25 bg-sky-500/[0.08] px-2 py-0.5 text-[10px] font-semibold text-sky-400"
              >
                {liveLoading ? <Loader2 className="h-2.5 w-2.5 animate-spin" /> : <RefreshCw className="h-2.5 w-2.5" />}
                Live
              </button>
            )}
            <span className="text-[11px] font-medium text-muted-foreground">
              Total {formatValue(total)}
            </span>
            <div className="flex items-center gap-1 rounded-lg border border-border bg-background/60 p-0.5">
              {CHART_TYPES.map((type) => (
                <button
                  key={type.id}
                  type="button"
                  disabled={!editable}
                  onClick={() => updateAttributes({ chartType: type.id })}
                  className={cn(
                    "rounded-md px-2.5 py-1 text-[11px] font-semibold transition-colors",
                    chartType === type.id
                      ? "bg-accent text-accent-foreground"
                      : "text-muted-foreground hover:text-foreground",
                  )}
                >
                  {type.label}
                </button>
              ))}
            </div>
          </div>
        </div>

        <div className="relative h-[240px] w-full">
          <ResponsiveContainer width="100%" height="100%">
            {chartType === "bar" ? (
              <BarChart data={data} margin={{ top: 8, right: 4, left: -20, bottom: 0 }}>
                <defs>
                  <linearGradient id="chartBarGrad" x1="0" y1="0" x2="0" y2="1">
                    <stop offset="0%" stopColor="#38bdf8" stopOpacity={1} />
                    <stop offset="100%" stopColor="#0284c7" stopOpacity={0.75} />
                  </linearGradient>
                </defs>
                <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" opacity={0.4} vertical={false} />
                <XAxis dataKey="label" tick={{ fontSize: 11, fill: "var(--muted-foreground)" }} axisLine={false} tickLine={false} />
                <YAxis tick={{ fontSize: 11, fill: "var(--muted-foreground)" }} axisLine={false} tickLine={false} width={40} />
                <Tooltip content={<ChartTooltip />} cursor={{ fill: "var(--accent)", opacity: 0.3 }} />
                <Bar dataKey="value" fill="url(#chartBarGrad)" radius={[6, 6, 0, 0]} maxBarSize={56} />
              </BarChart>
            ) : chartType === "line" ? (
              <AreaChart data={data} margin={{ top: 8, right: 4, left: -20, bottom: 0 }}>
                <defs>
                  <linearGradient id="chartAreaGrad" x1="0" y1="0" x2="0" y2="1">
                    <stop offset="0%" stopColor="#38bdf8" stopOpacity={0.35} />
                    <stop offset="100%" stopColor="#38bdf8" stopOpacity={0} />
                  </linearGradient>
                </defs>
                <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" opacity={0.4} vertical={false} />
                <XAxis dataKey="label" tick={{ fontSize: 11, fill: "var(--muted-foreground)" }} axisLine={false} tickLine={false} />
                <YAxis tick={{ fontSize: 11, fill: "var(--muted-foreground)" }} axisLine={false} tickLine={false} width={40} />
                <Tooltip content={<ChartTooltip />} cursor={{ stroke: "var(--border)" }} />
                <Area
                  type="monotone"
                  dataKey="value"
                  stroke="#38bdf8"
                  strokeWidth={2.5}
                  fill="url(#chartAreaGrad)"
                  dot={{ r: 3, fill: "#38bdf8", strokeWidth: 0 }}
                  activeDot={{ r: 5, strokeWidth: 0 }}
                />
              </AreaChart>
            ) : (
              <PieChart>
                <Tooltip content={<ChartTooltip />} />
                <Legend
                  verticalAlign="bottom"
                  height={28}
                  formatter={(value) => <span className="text-[11px] text-muted-foreground">{value}</span>}
                />
                <Pie data={data} dataKey="value" nameKey="label" innerRadius={52} outerRadius={82} paddingAngle={2}>
                  {data.map((point, index) => (
                    <Cell key={point.label + index} fill={PIE_COLORS[index % PIE_COLORS.length]} stroke="none" />
                  ))}
                </Pie>
              </PieChart>
            )}
          </ResponsiveContainer>

          {chartType === "pie" && (
            <div className="pointer-events-none absolute inset-0 flex flex-col items-center justify-center pb-7">
              <span className="text-[18px] font-bold text-foreground">{formatValue(total)}</span>
              <span className="text-[10px] uppercase tracking-wide text-muted-foreground">Total</span>
            </div>
          )}
        </div>

        {editable && !dataSource && (
          <div className="mt-3 space-y-1.5 border-t border-border pt-3">
            {data.map((point, index) => (
              <div key={index} className="flex items-center gap-2">
                <span
                  className="h-2.5 w-2.5 shrink-0 rounded-full"
                  style={{ backgroundColor: chartType === "pie" ? PIE_COLORS[index % PIE_COLORS.length] : "#38bdf8" }}
                />
                <input
                  value={point.label}
                  onChange={(e) => updatePoint(index, { label: e.target.value })}
                  className="min-w-0 flex-1 rounded-md border border-border bg-background px-2 py-1 text-[12px] outline-none focus:border-ring"
                />
                <input
                  type="number"
                  value={point.value}
                  onChange={(e) => updatePoint(index, { value: Number(e.target.value) || 0 })}
                  className="w-20 rounded-md border border-border bg-background px-2 py-1 text-[12px] outline-none focus:border-ring"
                />
                <button
                  type="button"
                  onClick={() => removePoint(index)}
                  className="text-muted-foreground transition-colors hover:text-destructive"
                >
                  <Trash2 className="h-3.5 w-3.5" />
                </button>
              </div>
            ))}
            <button
              type="button"
              onClick={addPoint}
              className="flex items-center gap-1.5 text-[12px] font-medium text-muted-foreground transition-colors hover:text-foreground"
            >
              <Plus className="h-3.5 w-3.5" />
              Add row
            </button>
          </div>
        )}
      </div>
    </NodeViewWrapper>
  );
}
