"use client";

import { useState, useMemo } from "react";
import {
  ScatterChart,
  Scatter,
  XAxis,
  YAxis,
  Tooltip,
  ResponsiveContainer,
  Cell,
  LineChart,
  Line,
  CartesianGrid,
} from "recharts";
import { useMerchants, useMerchantTransactions, MerchantRow } from "@/lib/hooks";
import { formatCategory } from "@/lib/categories";

function fmt(n: number) {
  return new Intl.NumberFormat("en-AU", {
    style: "currency",
    currency: "AUD",
    maximumFractionDigits: 0,
  }).format(n);
}
function fmtExact(n: number) {
  return new Intl.NumberFormat("en-AU", {
    style: "currency",
    currency: "AUD",
    minimumFractionDigits: 2,
  }).format(n);
}
function fmtDate(d: string) {
  return new Date(d + "T00:00:00").toLocaleDateString("en-AU", {
    day: "numeric",
    month: "short",
    year: "numeric",
  });
}

const CATEGORY_COLORS: Record<string, string> = {
  groceries: "#4ade80",
  dining: "#fb923c",
  transport: "#60a5fa",
  fuel: "#facc15",
  shopping: "#f472b6",
  utilities: "#a78bfa",
  entertainment: "#34d399",
  travel: "#38bdf8",
  health: "#f87171",
  insurance: "#94a3b8",
  subscriptions: "#c084fc",
  government: "#6b7280",
  education: "#fbbf24",
  rent: "#e879f9",
  home_goods: "#67e8f9",
  home_maintenance: "#c084fc",
  personal_care: "#fb7185",
  pets: "#a3e635",
  gifts: "#f9a8d4",
  charity: "#6ee7b7",
  other: "#71717a",
};

// Custom scatter tooltip
function ScatterTooltip({
  active,
  payload,
}: {
  active?: boolean;
  payload?: Array<{ payload: MerchantRow }>;
}) {
  if (!active || !payload?.length) return null;
  const d = payload[0].payload;
  return (
    <div className="bg-zinc-800 border border-zinc-700 rounded-lg p-3 text-sm shadow-xl max-w-48">
      <p className="font-semibold text-white truncate">{d.merchant}</p>
      <p className="text-zinc-400 text-xs mt-0.5">{formatCategory(d.category)}</p>
      <div className="mt-2 space-y-1 text-zinc-300">
        <p>{fmt(d.net_spend)} net</p>
        {d.refund_count > 0 && (
          <p className="text-emerald-400 text-xs">{d.refund_count} refund(s) −{fmt(d.total_refunds)}</p>
        )}
        <p>{d.debit_count}× transactions</p>
        <p>{fmtExact(d.avg_debit)} avg</p>
      </div>
    </div>
  );
}

// Quadrant labels
function QuadrantLabels({ medianX, medianY }: { medianX: number; medianY: number }) {
  return (
    <div className="absolute inset-0 pointer-events-none select-none">
      <div className="absolute top-2 right-4 text-xs text-zinc-600 text-right">
        high cost · frequent
      </div>
      <div className="absolute top-2 left-16 text-xs text-zinc-600">
        high cost · rare
      </div>
      <div className="absolute bottom-8 right-4 text-xs text-zinc-600 text-right">
        low cost · frequent
      </div>
      <div className="absolute bottom-8 left-16 text-xs text-zinc-600">
        low cost · rare
      </div>
    </div>
  );
}

// Merchant profile drawer
function MerchantProfile({
  merchant,
  onClose,
}: {
  merchant: MerchantRow;
  onClose: () => void;
}) {
  const { data } = useMerchantTransactions(merchant.merchant);
  const transactions = data?.transactions ?? [];

  // Build trend chart data from monthly_trend
  const trendData = useMemo(() => {
    const months = Object.keys(merchant.monthly_trend).sort();
    return months.map((m) => ({
      month: m,
      label: new Date(m + "-01").toLocaleDateString("en-AU", { month: "short", year: "2-digit" }),
      amount: merchant.monthly_trend[m],
    }));
  }, [merchant.monthly_trend]);

  const color = CATEGORY_COLORS[merchant.category] || "#6366f1";

  return (
    <div className="fixed inset-0 z-50 flex justify-end">
      {/* backdrop */}
      <div className="absolute inset-0 bg-black/60" onClick={onClose} />
      {/* drawer */}
      <div className="relative w-full max-w-lg bg-zinc-900 border-l border-zinc-700 h-full overflow-y-auto flex flex-col shadow-2xl">
        {/* Header */}
        <div className="flex items-start justify-between p-5 border-b border-zinc-800">
          <div className="flex-1 min-w-0 pr-4">
            <h2 className="text-lg font-semibold text-white truncate">{merchant.merchant}</h2>
            <span
              className="inline-block mt-1 px-2 py-0.5 rounded text-xs font-medium"
              style={{ background: color + "33", color }}
            >
              {formatCategory(merchant.category)}
            </span>
          </div>
          <button
            onClick={onClose}
            className="text-zinc-400 hover:text-white text-xl leading-none mt-0.5"
          >
            ×
          </button>
        </div>

        {/* Stats */}
        <div className="grid grid-cols-3 gap-3 p-5 border-b border-zinc-800">
          <div className="bg-zinc-800 rounded-lg p-3 text-center">
            <p className="text-xs text-zinc-400 mb-1">Net Spent</p>
            <p className="text-white font-semibold">{fmt(merchant.net_spend)}</p>
          </div>
          <div className="bg-zinc-800 rounded-lg p-3 text-center">
            <p className="text-xs text-zinc-400 mb-1">Avg per Visit</p>
            <p className="text-white font-semibold">{fmtExact(merchant.avg_debit)}</p>
          </div>
          <div className="bg-zinc-800 rounded-lg p-3 text-center">
            <p className="text-xs text-zinc-400 mb-1">Visits</p>
            <p className="text-white font-semibold">{merchant.debit_count}</p>
          </div>
        </div>
        {/* Refund callout — only show if there are refunds */}
        {merchant.refund_count > 0 && (
          <div className="mx-5 mt-3 px-3 py-2 rounded-lg bg-emerald-900/20 border border-emerald-800/40 flex items-center justify-between text-sm">
            <span className="text-emerald-400">
              {merchant.refund_count} refund{merchant.refund_count > 1 ? "s" : ""}
            </span>
            <span className="text-zinc-300">
              <span className="text-zinc-500 mr-2">gross {fmt(merchant.gross_spend)} − refunds</span>
              <span className="text-emerald-400 font-medium">−{fmt(merchant.total_refunds)}</span>
            </span>
          </div>
        )}

        {/* Trend chart */}
        {trendData.length > 1 && (
          <div className="p-5 border-b border-zinc-800">
            <p className="text-sm font-medium text-zinc-300 mb-3">Monthly Spend</p>
            <ResponsiveContainer width="100%" height={120}>
              <LineChart data={trendData}>
                <CartesianGrid stroke="#27272a" strokeDasharray="3 3" />
                <XAxis
                  dataKey="label"
                  tick={{ fill: "#71717a", fontSize: 10 }}
                  axisLine={false}
                  tickLine={false}
                />
                <YAxis
                  tick={{ fill: "#71717a", fontSize: 10 }}
                  axisLine={false}
                  tickLine={false}
                  tickFormatter={(v) => `$${Math.round(v)}`}
                  width={45}
                />
                <Tooltip
                  contentStyle={{ background: "#18181b", border: "1px solid #3f3f46", borderRadius: "8px" }}
                  labelStyle={{ color: "#a1a1aa" }}
                />
                <Line
                  type="monotone"
                  dataKey="amount"
                  stroke={color}
                  strokeWidth={2}
                  dot={{ fill: color, r: 3 }}
                />
              </LineChart>
            </ResponsiveContainer>
          </div>
        )}

        {/* Transaction history */}
        <div className="p-5 flex-1">
          <p className="text-sm font-medium text-zinc-300 mb-3">
            Transactions{" "}
            <span className="text-zinc-500 font-normal">({transactions.length})</span>
          </p>
          {transactions.length === 0 ? (
            <p className="text-zinc-500 text-sm">Loading…</p>
          ) : (
            <div className="space-y-1">
              {transactions.map((tx) => (
                <div
                  key={tx.id}
                  className="flex items-center justify-between py-2 border-b border-zinc-800 text-sm"
                >
                  <div className="flex-1 min-w-0 pr-3">
                    <p className="text-zinc-300 truncate">{tx.description}</p>
                    <p className="text-zinc-500 text-xs mt-0.5">
                      {fmtDate(tx.transaction_date)} · {tx.bank_name}
                    </p>
                  </div>
                  <p className="text-white font-medium whitespace-nowrap">
                    {fmtExact(tx.my_amount)}
                  </p>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

export default function MerchantsPage() {
  const [months, setMonths] = useState(12);
  const [selected, setSelected] = useState<MerchantRow | null>(null);
  const [search, setSearch] = useState("");

  const { data, isLoading } = useMerchants(months);
  const merchants = data?.merchants ?? [];

  // Stats for median lines
  const { medianX, medianY } = useMemo(() => {
    if (merchants.length === 0) return { medianX: 0, medianY: 0 };
    const counts = [...merchants].sort((a, b) => a.debit_count - b.debit_count);
    const spends = [...merchants].sort((a, b) => a.net_spend - b.net_spend);
    const mid = Math.floor(merchants.length / 2);
    return {
      medianX: counts[mid]?.debit_count ?? 0,
      medianY: spends[mid]?.net_spend ?? 0,
    };
  }, [merchants]);

  // Filtered merchants for the table
  const filtered = useMemo(() => {
    if (!search.trim()) return merchants;
    const q = search.toLowerCase();
    return merchants.filter((m) => m.merchant.toLowerCase().includes(q));
  }, [merchants, search]);

  // Top merchants for the scatter (max 150 for performance)
  const scatterData = useMemo(() => merchants.slice(0, 150), [merchants]);

  if (isLoading) {
    return (
      <div className="p-8 text-zinc-400">Loading merchant data…</div>
    );
  }

  return (
    <div className="p-6 max-w-6xl space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-xl font-semibold text-white">Merchants</h1>
          <p className="text-zinc-400 text-sm mt-0.5">{merchants.length} merchants · last {months} months</p>
        </div>
        <select
          value={months}
          onChange={(e) => setMonths(Number(e.target.value))}
          className="bg-zinc-800 border border-zinc-700 rounded-md text-sm text-zinc-200 px-3 py-1.5"
        >
          <option value={3}>3 months</option>
          <option value={6}>6 months</option>
          <option value={12}>12 months</option>
          <option value={24}>24 months</option>
        </select>
      </div>

      {/* Scatter plot */}
      <div className="bg-zinc-900 border border-zinc-800 rounded-xl p-5">
        <h2 className="text-sm font-medium text-zinc-300 mb-1">Spend vs Frequency</h2>
        <p className="text-xs text-zinc-500 mb-4">
          Each dot = one merchant. Click to open profile.
        </p>
        <div className="relative">
          <QuadrantLabels medianX={medianX} medianY={medianY} />
          <ResponsiveContainer width="100%" height={360}>
            <ScatterChart margin={{ top: 10, right: 20, bottom: 20, left: 10 }}>
              <CartesianGrid stroke="#27272a" strokeDasharray="3 3" />
              <XAxis
                dataKey="debit_count"
                name="Transactions"
                type="number"
                tick={{ fill: "#71717a", fontSize: 11 }}
                axisLine={false}
                tickLine={false}
                label={{ value: "Transaction Count", position: "insideBottom", offset: -10, fill: "#52525b", fontSize: 11 }}
              />
              <YAxis
                dataKey="net_spend"
                name="Net Spend"
                type="number"
                tick={{ fill: "#71717a", fontSize: 11 }}
                axisLine={false}
                tickLine={false}
                tickFormatter={(v) => `$${Math.round(v / 1000)}k`}
                width={48}
                label={{ value: "Total Spend", angle: -90, position: "insideLeft", offset: 10, fill: "#52525b", fontSize: 11 }}
              />
              <Tooltip content={<ScatterTooltip />} cursor={{ strokeDasharray: "3 3", stroke: "#52525b" }} />
              <Scatter
                data={scatterData}
                onClick={(d) => setSelected(d as unknown as MerchantRow)}
                style={{ cursor: "pointer" }}
              >
                {scatterData.map((entry, idx) => (
                  <Cell
                    key={idx}
                    fill={CATEGORY_COLORS[entry.category] || "#6366f1"}
                    fillOpacity={0.75}
                    stroke={selected?.merchant === entry.merchant ? "#fff" : "transparent"}
                    strokeWidth={2}
                  />
                ))}
              </Scatter>
            </ScatterChart>
          </ResponsiveContainer>
        </div>
        {/* Category legend */}
        <div className="mt-3 flex flex-wrap gap-x-4 gap-y-1">
          {Object.entries(CATEGORY_COLORS)
            .filter(([cat]) => merchants.some((m) => m.category === cat))
            .slice(0, 12)
            .map(([cat, color]) => (
              <span key={cat} className="flex items-center gap-1.5 text-xs text-zinc-400">
                <span className="w-2 h-2 rounded-full inline-block" style={{ background: color }} />
                {formatCategory(cat)}
              </span>
            ))}
        </div>
      </div>

      {/* Merchant table */}
      <div className="bg-zinc-900 border border-zinc-800 rounded-xl overflow-hidden">
        <div className="flex items-center justify-between p-4 border-b border-zinc-800">
          <h2 className="text-sm font-medium text-zinc-300">All Merchants</h2>
          <input
            type="text"
            placeholder="Search…"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            className="bg-zinc-800 border border-zinc-700 rounded-md text-sm text-zinc-200 placeholder-zinc-500 px-3 py-1.5 w-48"
          />
        </div>
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-zinc-500 text-xs border-b border-zinc-800">
                <th className="text-left px-4 py-2 font-medium">Merchant</th>
                <th className="text-left px-4 py-2 font-medium">Category</th>
                <th className="text-right px-4 py-2 font-medium">Total</th>
                <th className="text-right px-4 py-2 font-medium">Count</th>
                <th className="text-right px-4 py-2 font-medium">Avg</th>
                <th className="text-right px-4 py-2 font-medium hidden sm:table-cell">Last Seen</th>
              </tr>
            </thead>
            <tbody>
              {filtered.map((m) => {
                const color = CATEGORY_COLORS[m.category] || "#6366f1";
                return (
                  <tr
                    key={m.merchant}
                    onClick={() => setSelected(m)}
                    className="border-b border-zinc-800 hover:bg-zinc-800 cursor-pointer transition-colors"
                  >
                    <td className="px-4 py-2.5 text-zinc-200 max-w-[200px]">
                      <span className="truncate block">{m.merchant}</span>
                    </td>
                    <td className="px-4 py-2.5">
                      <span
                        className="px-1.5 py-0.5 rounded text-xs"
                        style={{ background: color + "22", color }}
                      >
                        {formatCategory(m.category)}
                      </span>
                    </td>
                    <td className="px-4 py-2.5 text-right text-white font-medium">
                      {fmt(m.net_spend)}
                      {m.refund_count > 0 && (
                        <span className="ml-1.5 text-emerald-400 text-xs">↩{m.refund_count}</span>
                      )}
                    </td>
                    <td className="px-4 py-2.5 text-right text-zinc-400">{m.debit_count}</td>
                    <td className="px-4 py-2.5 text-right text-zinc-400">
                      {fmtExact(m.avg_debit)}
                    </td>
                    <td className="px-4 py-2.5 text-right text-zinc-500 text-xs hidden sm:table-cell">
                      {fmtDate(m.last_seen)}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      {/* Merchant profile drawer */}
      {selected && (
        <MerchantProfile merchant={selected} onClose={() => setSelected(null)} />
      )}
    </div>
  );
}
