"use client";

import { useEffect, useMemo, useState } from "react";
import { useRuleMatches, useApplyRuleToSelection, type RuleMatchChange } from "@/lib/hooks";
import { formatCategory } from "@/lib/categories";

/**
 * Preview what a rule would do, then apply it to a chosen subset.
 *
 * The apply path takes explicit transaction ids rather than re-running the
 * conditions, so what you tick is exactly what changes — a rule whose
 * conditions are too broad cannot quietly reach further than the preview showed.
 */

function fmt(amount: number, currency = "AUD") {
  return new Intl.NumberFormat("en-AU", { style: "currency", currency }).format(amount);
}

function describe(c: RuleMatchChange) {
  if (c.field === "category") return `${formatCategory(c.from)} → ${formatCategory(c.to)}`;
  if (c.field === "merchant") return `${c.from ?? "—"} → ${c.to}`;
  if (c.field === "tags") return `+ tags`;
  return c.from ? `split ${c.from} → ${c.to}` : `split → ${c.to}`;
}

export function RulePreviewModal({
  ruleId,
  ruleName,
  onClose,
}: {
  ruleId: number;
  ruleName: string;
  onClose: () => void;
}) {
  const { data, isLoading, error } = useRuleMatches(ruleId);
  const apply = useApplyRuleToSelection();
  const [selected, setSelected] = useState<Set<number>>(new Set());
  const [done, setDone] = useState<string | null>(null);

  // Default to everything the rule would change — the common case is "yes, all
  // of these", with deselection as the exception.
  useEffect(() => {
    if (data?.transactions) setSelected(new Set(data.transactions.map((t) => t.id)));
  }, [data]);

  const rows = data?.transactions ?? [];
  const allSelected = rows.length > 0 && selected.size === rows.length;
  const totalValue = useMemo(
    () => rows.filter((r) => selected.has(r.id))
              .reduce((a, r) => a + Number(r.amount_aud ?? r.amount), 0),
    [rows, selected]
  );

  return (
    <div className="fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4">
      <div className="bg-zinc-900 border border-zinc-700 rounded-lg w-full max-w-4xl max-h-[85vh] flex flex-col">
        <div className="px-5 py-4 border-b border-zinc-800">
          <h2 className="text-lg font-medium">Preview: {ruleName}</h2>
          {data && (
            <p className="text-xs text-zinc-500 mt-1">
              {data.total_matched} matched · <span className="text-amber-400">{data.would_change} would change</span>
              {data.already_correct > 0 && ` · ${data.already_correct} already correct`}
            </p>
          )}
          {data?.rule.matches_everything && (
            <p className="text-xs text-red-400 mt-1">
              This rule has no conditions — it matches every transaction.
            </p>
          )}
        </div>

        <div className="flex-1 overflow-auto px-5 py-3">
          {isLoading && <p className="text-sm text-zinc-500">Checking…</p>}
          {error && <p className="text-sm text-red-400">Failed to load matches.</p>}
          {data && rows.length === 0 && (
            <p className="text-sm text-zinc-500">
              Nothing would change{data.already_correct > 0 && ` — all ${data.already_correct} matching transactions already have these values`}.
            </p>
          )}
          {rows.length > 0 && (
            <table className="w-full text-xs">
              <thead className="sticky top-0 bg-zinc-900">
                <tr className="border-b border-zinc-800 text-zinc-500">
                  <th className="p-2 w-8">
                    <input
                      type="checkbox"
                      checked={allSelected}
                      onChange={(e) =>
                        setSelected(e.target.checked ? new Set(rows.map((r) => r.id)) : new Set())
                      }
                    />
                  </th>
                  <th className="text-left p-2">Date</th>
                  <th className="text-left p-2">Description</th>
                  <th className="text-right p-2">Amount</th>
                  <th className="text-left p-2">Would change</th>
                </tr>
              </thead>
              <tbody>
                {rows.map((r) => (
                  <tr key={r.id} className="border-b border-zinc-800/40 hover:bg-zinc-800/30">
                    <td className="p-2">
                      <input
                        type="checkbox"
                        checked={selected.has(r.id)}
                        onChange={(e) => {
                          const next = new Set(selected);
                          if (e.target.checked) next.add(r.id); else next.delete(r.id);
                          setSelected(next);
                        }}
                      />
                    </td>
                    <td className="p-2 text-zinc-500 whitespace-nowrap">{String(r.transaction_date).slice(0, 10)}</td>
                    <td className="p-2 text-zinc-300 max-w-[280px] truncate" title={r.description}>
                      {r.effective_merchant || r.description}
                      <span className="text-zinc-600 ml-2">{r.bank_name}</span>
                    </td>
                    <td className="p-2 text-right tabular-nums text-zinc-400">
                      {fmt(Number(r.amount_aud ?? r.amount))}
                    </td>
                    <td className="p-2 text-amber-400">
                      {r.changes.map((c, i) => <div key={i}>{describe(c)}</div>)}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
          {data?.truncated && (
            <p className="text-xs text-zinc-500 mt-2">Showing the first {rows.length} — narrow the rule to see the rest.</p>
          )}
        </div>

        <div className="px-5 py-3 border-t border-zinc-800 flex items-center justify-between">
          <span className="text-xs text-zinc-500">
            {done ?? `${selected.size} selected · ${fmt(totalValue)}`}
          </span>
          <div className="flex gap-2">
            <button onClick={onClose} className="px-3 py-1.5 text-sm text-zinc-400 hover:text-white">
              Close
            </button>
            <button
              disabled={selected.size === 0 || apply.isPending}
              onClick={() =>
                apply.mutate(
                  { ruleId, ids: Array.from(selected) },
                  {
                    onSuccess: () => {
                      setDone(`Applied to ${selected.size} transaction${selected.size !== 1 ? "s" : ""}`);
                      setSelected(new Set());
                    },
                  }
                )
              }
              className="px-3 py-1.5 bg-emerald-700 hover:bg-emerald-600 disabled:opacity-40 rounded text-sm"
            >
              {apply.isPending ? "Applying…" : `Apply to ${selected.size}`}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}
