"use client";

import { useState, useMemo } from "react";
import Link from "next/link";
import { useStatements, useParticipants, useUpdateStatement } from "@/lib/hooks";
import {
  STATEMENT_TYPES,
  STATEMENT_TYPE_LABELS,
  asStatementType,
  isLiability,
} from "@/lib/statement-types";

function formatDate(d: string | null) {
  if (!d) return "—";
  return new Date(d).toLocaleDateString("en-AU", {
    day: "2-digit",
    month: "short",
    year: "numeric",
  });
}

function formatPeriod(start: string | null, end: string | null) {
  if (!start && !end) return "—";
  const fmt = (d: string) =>
    new Date(d).toLocaleDateString("en-AU", { day: "2-digit", month: "short", year: "2-digit" });
  if (!start) return `until ${fmt(end!)}`;
  if (!end) return `from ${fmt(start)}`;
  return `${fmt(start)} – ${fmt(end)}`;
}

function formatAmount(n: number | null): string {
  if (n === null || n === undefined) return "—";
  return new Intl.NumberFormat("en-AU", {
    style: "currency",
    currency: "AUD",
    minimumFractionDigits: 2,
  }).format(Number(n));
}

const selectCls =
  "bg-zinc-900 border border-zinc-700 rounded text-xs px-2 py-1.5 text-zinc-300 cursor-pointer hover:border-zinc-600 focus:outline-none focus:border-indigo-500";

export default function StatementsPage() {
  const { data: statements, isLoading } = useStatements();
  const { data: participants } = useParticipants();
  const updateStatement = useUpdateStatement();

  const [bankFilter, setBankFilter] = useState("");
  const [typeFilter, setTypeFilter] = useState<"all" | (typeof STATEMENT_TYPES)[number]>("all");
  const [ownerFilter, setOwnerFilter] = useState("");
  const [yearFilter, setYearFilter] = useState("");

  const banks = useMemo(
    () => [...new Set((statements ?? []).map((s) => s.bank_name))].sort(),
    [statements]
  );
  const years = useMemo(
    () =>
      [
        ...new Set(
          (statements ?? [])
            .map((s) => s.billing_end_date?.slice(0, 4))
            .filter(Boolean) as string[]
        ),
      ].sort((a, b) => b.localeCompare(a)),
    [statements]
  );

  const filtered = useMemo(() => {
    if (!statements) return [];
    return statements.filter((s) => {
      if (bankFilter && s.bank_name !== bankFilter) return false;
      if (typeFilter !== "all" && asStatementType(s.statement_type) !== typeFilter) return false;
      if (ownerFilter && String(s.owner_id) !== ownerFilter) return false;
      if (yearFilter && s.billing_end_date?.slice(0, 4) !== yearFilter) return false;
      return true;
    });
  }, [statements, bankFilter, typeFilter, ownerFilter, yearFilter]);

  const hasFilters = bankFilter || typeFilter !== "all" || ownerFilter || yearFilter;

  return (
    <div>
      <div className="flex items-center justify-between mb-4">
        <h2 className="text-2xl font-display">Statements</h2>
        {!isLoading && statements && (
          <span className="text-xs text-zinc-500">
            {hasFilters ? `${filtered.length} of ${statements.length}` : statements.length} statements
          </span>
        )}
      </div>

      {/* Filters */}
      {!isLoading && statements && (
        <div className="flex flex-wrap gap-2 mb-4">
          <select value={bankFilter} onChange={(e) => setBankFilter(e.target.value)} className={selectCls}>
            <option value="">All banks</option>
            {banks.map((b) => (
              <option key={b} value={b}>{b}</option>
            ))}
          </select>

          <select value={typeFilter} onChange={(e) => setTypeFilter(e.target.value as typeof typeFilter)} className={selectCls}>
            <option value="all">All types</option>
            {STATEMENT_TYPES.map((t) => (
              <option key={t} value={t}>{STATEMENT_TYPE_LABELS[t]}</option>
            ))}
          </select>

          {participants && participants.length > 1 && (
            <select value={ownerFilter} onChange={(e) => setOwnerFilter(e.target.value)} className={selectCls}>
              <option value="">All owners</option>
              {participants.map((p) => (
                <option key={p.id} value={String(p.id)}>{p.name}</option>
              ))}
            </select>
          )}

          <select value={yearFilter} onChange={(e) => setYearFilter(e.target.value)} className={selectCls}>
            <option value="">All years</option>
            {years.map((y) => (
              <option key={y} value={y}>{y}</option>
            ))}
          </select>

          {hasFilters && (
            <button
              onClick={() => { setBankFilter(""); setTypeFilter("all"); setOwnerFilter(""); setYearFilter(""); }}
              className="text-xs text-zinc-500 hover:text-zinc-300 px-2 py-1.5 transition-colors"
            >
              × Clear
            </button>
          )}
        </div>
      )}

      {isLoading ? (
        <p className="text-zinc-500 text-sm">Loading...</p>
      ) : !filtered.length ? (
        <p className="text-zinc-500 text-sm">{hasFilters ? "No statements match filters" : "No statements found"}</p>
      ) : (
        <div className="border border-zinc-700 rounded-xl overflow-x-auto">
          <table className="w-full text-sm min-w-[800px]">
            <thead>
              <tr className="border-b border-zinc-800 bg-zinc-900">
                <th className="text-left px-3 py-2.5 text-xs text-zinc-600 font-medium w-8">#</th>
                <th className="text-left px-4 py-2.5 text-xs text-zinc-500 font-medium sticky left-0 z-10 bg-zinc-900 border-r border-zinc-800/80">Bank</th>
                <th className="text-left px-4 py-2.5 text-xs text-zinc-500 font-medium">Account</th>
                <th className="text-left px-4 py-2.5 text-xs text-zinc-500 font-medium">Period</th>
                <th className="text-left px-4 py-2.5 text-xs text-zinc-500 font-medium">Due / End</th>
                <th className="text-left px-4 py-2.5 text-xs text-zinc-500 font-medium">Ccy</th>
                <th className="text-right px-4 py-2.5 text-xs text-zinc-500 font-medium">Amount</th>
                <th className="text-right px-4 py-2.5 text-xs text-zinc-500 font-medium">Txns</th>
                <th className="text-left px-4 py-2.5 text-xs text-zinc-500 font-medium">Owner</th>
                <th className="px-4 py-2.5 hidden sm:table-cell"></th>
              </tr>
            </thead>
            <tbody>
              {filtered.map((s, idx) => {
                const stmtType = asStatementType(s.statement_type);
                const owed = isLiability(s.statement_type);
                // Cards headline the amount due; everything else (including loans,
                // where the balance is what's still owed) headlines the balance.
                const displayAmount =
                  stmtType === "credit_card" ? s.total_amount_due : s.closing_balance;
                const amount = Number(displayAmount);
                const amountColor = owed
                  ? "text-red-400"
                  : amount >= 0
                  ? "text-green-400"
                  : "text-red-400";

                return (
                  <tr key={s.id} className="border-b border-zinc-800/50 hover:bg-zinc-800/20 transition-colors">
                    <td className="px-3 py-3 text-xs text-zinc-600 tabular-nums">{idx + 1}</td>
                    <td className="px-4 py-3 sticky left-0 z-10 bg-zinc-950 border-r border-zinc-800/80">
                      <div className="font-medium truncate max-w-[160px]" title={s.bank_name}>
                        {s.bank_name}
                      </div>
                      {s.card_name && (
                        <div className="text-xs text-zinc-500 truncate max-w-[160px]">{s.card_name}</div>
                      )}
                      {stmtType === "loan" && (s.interest_rate || s.scheduled_repayment) && (
                        <div className="text-xs text-zinc-500 truncate max-w-[160px]">
                          {[
                            s.interest_rate ? `${Number(s.interest_rate).toFixed(2)}% p.a.` : null,
                            s.scheduled_repayment
                              ? `${formatAmount(s.scheduled_repayment)}${
                                  s.repayment_frequency ? ` ${s.repayment_frequency}` : ""
                                }`
                              : null,
                          ]
                            .filter(Boolean)
                            .join(" · ")}
                        </div>
                      )}
                      <Link
                        href={`/transactions?statement_id=${s.id}`}
                        className="sm:hidden text-xs text-indigo-400 hover:text-indigo-300 mt-1 inline-block"
                      >
                        View →
                      </Link>
                    </td>
                    <td className="px-4 py-3 text-zinc-400 font-mono text-xs">
                      {s.account_number}
                    </td>
                    <td className="px-4 py-3 text-zinc-400 whitespace-nowrap">
                      {formatPeriod(s.billing_start_date, s.billing_end_date)}
                      {/* An account cannot be billed twice for the same day, so
                          an overlap means these transactions are in the ledger
                          twice. Red rather than amber: the balance warning above
                          means a statement doesn't add up, this means the data is
                          double-counted everywhere it is summed. */}
                      {s.overlaps?.length > 0 && (
                        <div
                          className="text-[10px] text-red-400 mt-0.5"
                          title={`Billing period overlaps statement ${s.overlaps
                            .map((o) => `#${o.id} by ${o.days} day${o.days === 1 ? "" : "s"}`)
                            .join(", ")}. The overlapping transactions are likely imported twice.`}
                        >
                          ⚠ overlaps #{s.overlaps.map((o) => o.id).join(", #")}
                        </div>
                      )}
                    </td>
                    <td className="px-4 py-3 text-zinc-400 whitespace-nowrap">
                      {formatDate(s.payment_due_date ?? s.billing_end_date)}
                    </td>
                    <td className="px-4 py-3 text-zinc-500 text-xs">
                      {s.currency}
                    </td>
                    <td className="px-4 py-3 text-right tabular-nums">
                      {displayAmount !== null && displayAmount !== undefined ? (
                        <span className={amountColor}>{formatAmount(displayAmount)}</span>
                      ) : (
                        <span className="text-zinc-600">—</span>
                      )}
                    </td>
                    <td className="px-4 py-3 text-right text-zinc-500">
                      {s.transaction_count}
                      {/* Balance assertion: flags statements whose transactions
                          don't add up to the closing balance. */}
                      {s.balance_diff !== null && s.balance_diff !== undefined &&
                        Math.abs(Number(s.balance_diff)) >= 0.02 && (
                        <div
                          className="text-[10px] text-amber-400 mt-0.5 whitespace-nowrap"
                          title={`Transactions don't reconcile: expected closing ${formatAmount(
                            s.expected_closing
                          )}, statement says ${formatAmount(s.closing_balance)}`}
                        >
                          ⚠ {formatAmount(Math.abs(Number(s.balance_diff)))} off
                        </div>
                      )}
                    </td>
                    <td className="px-4 py-3">
                      {participants?.length ? (
                        <select
                          value={s.owner_id ?? ""}
                          onChange={(e) => {
                            const next = Number(e.target.value);
                            const name = participants.find((p) => p.id === next)?.name ?? "them";
                            // This page only lists statements you own, so handing
                            // one over removes it — and every transaction on it —
                            // from your view, and only they can hand it back.
                            if (
                              !confirm(
                                `Reassign this statement to ${name}?\n\nEvery transaction on it moves to their ledger, and the statement leaves your list — only ${name} can move it back.`
                              )
                            ) {
                              return;
                            }
                            updateStatement.mutate(
                              { id: s.id, owner_id: next },
                              { onError: (err) => alert(err instanceof Error ? err.message : "Failed to reassign") }
                            );
                          }}
                          className="bg-zinc-800 border border-zinc-700 rounded text-xs px-2 py-1 text-zinc-300 cursor-pointer hover:border-zinc-600 focus:outline-none focus:border-indigo-500"
                        >
                          {participants.map((p) => (
                            <option key={p.id} value={p.id}>{p.name}</option>
                          ))}
                        </select>
                      ) : (
                        <span className="text-zinc-600 text-xs">{s.owner_name}</span>
                      )}
                    </td>
                    <td className="px-4 py-3 hidden sm:table-cell">
                      <Link
                        href={`/transactions?statement_id=${s.id}`}
                        className="px-3 py-1 bg-zinc-800 hover:bg-zinc-700 rounded text-xs transition-colors whitespace-nowrap"
                      >
                        View →
                      </Link>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}
