import { useState, useRef } from "react";
import { useParams, Link } from "react-router-dom";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { getAccounts, previewImport, importCsvToAccount, type CsvMapping } from "@/api/accounts";
import { getTransactions } from "@/api/transactions";
import { formatCurrency } from "@/utils/currency";
import { cn } from "@/utils/cn";
import { format } from "date-fns";
import {
  ArrowLeft, Upload, FileText, XCircle, Loader2, CheckCircle,
  ArrowUpCircle, ArrowDownCircle, ArrowLeftRight, ChevronLeft, ChevronRight,
} from "lucide-react";

export default function AccountDetail() {
  const { accountId } = useParams<{ accountId: string }>();
  const qc = useQueryClient();
  const [showImport, setShowImport] = useState(false);
  const [page, setPage] = useState(1);

  const { data: accounts = [] } = useQuery({ queryKey: ["accounts"], queryFn: getAccounts });
  const account = accounts.find(a => a.id === accountId);

  const { data: txnData, isLoading: txnLoading } = useQuery({
    queryKey: ["transactions", { account_id: accountId, page, page_size: 25 }],
    queryFn: () => getTransactions({ account_id: accountId, page, page_size: 25 }),
    enabled: !!accountId,
  });

  if (!account) {
    return (
      <div className="flex items-center justify-center h-64 text-muted-foreground">
        <p>Account not found</p>
      </div>
    );
  }

  const isLiability = ["credit_card", "loan", "mortgage"].includes(account.type);
  const utilPct = account.credit_limit && account.credit_limit > 0
    ? Math.min(100, (Math.abs(account.current_balance) / account.credit_limit) * 100)
    : null;

  return (
    <div className="space-y-6">
      {/* Back + header */}
      <div className="flex items-center gap-3">
        <Link to="/accounts" className="p-2 rounded-lg hover:bg-secondary transition-colors text-muted-foreground">
          <ArrowLeft className="w-5 h-5" />
        </Link>
        <div className="flex-1">
          <h1 className="text-2xl font-bold">{account.name}</h1>
          <p className="text-sm text-muted-foreground">
            {account.institution && `${account.institution} · `}
            {account.type.replace(/_/g, " ")} · {account.currency}
          </p>
        </div>
        <button
          onClick={() => setShowImport(true)}
          className="flex items-center gap-2 bg-primary text-primary-foreground px-4 py-2 rounded-lg text-sm font-medium hover:bg-primary/90 transition-colors"
        >
          <Upload className="w-4 h-4" />
          Import CSV
        </button>
      </div>

      {/* Account stats */}
      <div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
        <div className="bg-card border border-border rounded-xl p-4">
          <p className="text-xs text-muted-foreground mb-1">Current Balance</p>
          <p className={cn("text-xl font-bold tabular-nums", isLiability ? "text-destructive" : "text-foreground")}>
            {formatCurrency(account.current_balance, account.currency)}
          </p>
        </div>
        {account.credit_limit != null && (
          <div className="bg-card border border-border rounded-xl p-4">
            <p className="text-xs text-muted-foreground mb-1">Credit Limit</p>
            <p className="text-xl font-bold tabular-nums">{formatCurrency(account.credit_limit, account.currency)}</p>
          </div>
        )}
        {account.interest_rate != null && (
          <div className="bg-card border border-border rounded-xl p-4">
            <p className="text-xs text-muted-foreground mb-1">Interest Rate</p>
            <p className="text-xl font-bold">{Number(account.interest_rate).toFixed(2)}% p.a.</p>
          </div>
        )}
        {txnData && (
          <div className="bg-card border border-border rounded-xl p-4">
            <p className="text-xs text-muted-foreground mb-1">Total Transactions</p>
            <p className="text-xl font-bold tabular-nums">{txnData.total}</p>
          </div>
        )}
      </div>

      {/* Credit utilisation */}
      {utilPct !== null && (
        <div className="bg-card border border-border rounded-xl p-4">
          <div className="flex justify-between text-sm mb-2">
            <span className="font-medium">Credit Utilisation</span>
            <span className={cn("font-semibold", utilPct > 80 ? "text-destructive" : utilPct > 50 ? "text-yellow-500" : "text-success")}>
              {utilPct.toFixed(0)}%
            </span>
          </div>
          <div className="h-2 bg-secondary rounded-full overflow-hidden">
            <div
              className={cn("h-full rounded-full transition-all", utilPct > 80 ? "bg-destructive" : utilPct > 50 ? "bg-yellow-500" : "bg-success")}
              style={{ width: `${utilPct}%` }}
            />
          </div>
          <p className="text-xs text-muted-foreground mt-1">
            {formatCurrency(Math.abs(account.current_balance), account.currency)} used of {formatCurrency(account.credit_limit!, account.currency)}
          </p>
        </div>
      )}

      {account.notes && (
        <div className="bg-card border border-border rounded-xl p-4">
          <p className="text-xs text-muted-foreground mb-1">Notes</p>
          <p className="text-sm">{account.notes}</p>
        </div>
      )}

      {/* Transactions */}
      <div className="bg-card border border-border rounded-xl overflow-hidden">
        <div className="flex items-center justify-between px-5 py-4 border-b border-border">
          <p className="font-semibold">Transactions</p>
          {txnData && txnData.pages > 1 && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <span>Page {page} of {txnData.pages}</span>
              <button onClick={() => setPage(p => Math.max(1, p - 1))} disabled={page === 1} className="p-1 rounded hover:bg-secondary disabled:opacity-40">
                <ChevronLeft className="w-4 h-4" />
              </button>
              <button onClick={() => setPage(p => Math.min(txnData.pages, p + 1))} disabled={page === txnData.pages} className="p-1 rounded hover:bg-secondary disabled:opacity-40">
                <ChevronRight className="w-4 h-4" />
              </button>
            </div>
          )}
        </div>

        {txnLoading ? (
          <div className="space-y-px">
            {[1, 2, 3, 4, 5].map(i => <div key={i} className="h-14 bg-secondary/20 animate-pulse" />)}
          </div>
        ) : !txnData?.items.length ? (
          <div className="py-16 text-center text-muted-foreground text-sm">
            No transactions yet.{" "}
            <button onClick={() => setShowImport(true)} className="text-primary hover:underline">Import from CSV</button>
          </div>
        ) : (
          <div>
            {txnData.items.map(txn => (
              <div key={txn.id} className="flex items-center gap-3 px-5 py-3 border-b border-border/50 hover:bg-secondary/20 transition-colors">
                <div className={cn("p-1.5 rounded-lg shrink-0",
                  txn.type === "income" ? "bg-success/10" :
                  txn.type === "transfer" ? "bg-primary/10" : "bg-destructive/10"
                )}>
                  {txn.type === "income"
                    ? <ArrowUpCircle className="w-3.5 h-3.5 text-success" />
                    : txn.type === "transfer"
                    ? <ArrowLeftRight className="w-3.5 h-3.5 text-primary" />
                    : <ArrowDownCircle className="w-3.5 h-3.5 text-destructive" />}
                </div>
                <div className="flex-1 min-w-0">
                  <p className="text-sm font-medium truncate">{txn.description}</p>
                  <p className="text-xs text-muted-foreground">{format(new Date(txn.date), "dd MMM yyyy")}</p>
                </div>
                <p className={cn("text-sm font-semibold tabular-nums shrink-0",
                  txn.type === "income" ? "text-success" :
                  txn.type === "expense" ? "text-destructive" : "text-muted-foreground"
                )}>
                  {Number(txn.amount) > 0 ? "+" : ""}{formatCurrency(txn.amount, txn.currency)}
                </p>
              </div>
            ))}
          </div>
        )}
      </div>

      {showImport && account && (
        <ImportModal
          accountId={account.id}
          accountName={account.name}
          onClose={() => setShowImport(false)}
          onSuccess={() => {
            qc.invalidateQueries({ queryKey: ["transactions"] });
            qc.invalidateQueries({ queryKey: ["accounts"] });
            qc.invalidateQueries({ queryKey: ["net-worth"] });
          }}
        />
      )}
    </div>
  );
}

// ─── Import Modal ─────────────────────────────────────────────────────────────

type ImportStep = "upload" | "preview" | "done";

function ImportModal({
  accountId, accountName, onClose, onSuccess,
}: {
  accountId: string;
  accountName: string;
  onClose: () => void;
  onSuccess: () => void;
}) {
  const fileRef = useRef<HTMLInputElement>(null);
  const [step, setStep] = useState<ImportStep>("upload");
  const [file, setFile] = useState<File | null>(null);
  const [preview, setPreview] = useState<Awaited<ReturnType<typeof previewImport>> | null>(null);
  const [mapping, setMapping] = useState<CsvMapping | null>(null);
  const [result, setResult] = useState<{ imported: number; skipped: number } | null>(null);
  const [detecting, setDetecting] = useState(false);
  const [detectError, setDetectError] = useState<string | null>(null);

  const importMutation = useMutation({
    mutationFn: () => importCsvToAccount(accountId, file!, mapping!),
    onSuccess: (data) => {
      setResult(data);
      setStep("done");
      onSuccess();
    },
  });

  async function handleFileSelect(f: File) {
    setFile(f);
    setDetecting(true);
    setDetectError(null);
    try {
      const p = await previewImport(accountId, f);
      setPreview(p);
      setMapping(p.mapping);
      setStep("preview");
    } catch (e: any) {
      setDetectError(e?.response?.data?.detail ?? "Failed to read file");
    } finally {
      setDetecting(false);
    }
  }

  function onDrop(e: React.DragEvent) {
    e.preventDefault();
    const f = e.dataTransfer.files[0];
    if (f?.name.toLowerCase().endsWith(".csv")) handleFileSelect(f);
  }

  const isSplit = mapping ? (!!mapping.debit && !!mapping.credit) : false;

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm">
      <div className="bg-card border border-border rounded-2xl w-full max-w-2xl max-h-[90vh] overflow-y-auto shadow-xl">
        {/* Header */}
        <div className="flex items-center justify-between p-5 border-b border-border">
          <div>
            <h2 className="font-semibold text-lg">Import CSV</h2>
            <p className="text-xs text-muted-foreground mt-0.5">into {accountName}</p>
          </div>
          <button onClick={onClose} className="p-1.5 rounded-lg hover:bg-secondary text-muted-foreground">
            <XCircle className="w-5 h-5" />
          </button>
        </div>

        <div className="p-5 space-y-5">
          {/* Step: upload */}
          {step === "upload" && (
            <>
              <div
                onDrop={onDrop}
                onDragOver={e => e.preventDefault()}
                onClick={() => fileRef.current?.click()}
                className="border-2 border-dashed border-border rounded-xl p-10 text-center cursor-pointer hover:border-primary/50 transition-colors"
              >
                {detecting ? (
                  <div className="flex flex-col items-center gap-2 text-muted-foreground">
                    <Loader2 className="w-8 h-8 animate-spin text-primary" />
                    <p className="text-sm">Detecting format…</p>
                  </div>
                ) : (
                  <div className="text-muted-foreground">
                    <Upload className="w-8 h-8 mx-auto mb-2 opacity-50" />
                    <p className="text-sm font-medium">Drop your bank CSV here</p>
                    <p className="text-xs mt-1 opacity-60">Supports Monzo, Starling, Revolut, Barclays, Lloyds, NatWest, HSBC, Santander, Nationwide</p>
                  </div>
                )}
                <input
                  ref={fileRef}
                  type="file"
                  accept=".csv"
                  className="hidden"
                  onChange={e => { const f = e.target.files?.[0]; if (f) handleFileSelect(f); }}
                />
              </div>
              {detectError && <p className="text-destructive text-sm text-center">{detectError}</p>}
            </>
          )}

          {/* Step: preview + mapping */}
          {step === "preview" && preview && mapping && (
            <>
              {/* Detected format badge */}
              <div className={cn(
                "flex items-center gap-2 px-3 py-2 rounded-lg text-sm",
                preview.detected_format ? "bg-success/10 text-success" : "bg-yellow-500/10 text-yellow-600"
              )}>
                {preview.detected_format ? (
                  <><CheckCircle className="w-4 h-4 shrink-0" /> Detected: <strong>{preview.detected_format}</strong></>
                ) : (
                  <><FileText className="w-4 h-4 shrink-0" /> Unknown format — please verify column mapping below</>
                )}
                <span className="ml-auto text-xs opacity-70">{preview.total_rows} rows</span>
              </div>

              {/* Column mapping */}
              <div>
                <p className="text-sm font-semibold mb-3">Column Mapping</p>
                <div className="grid grid-cols-2 gap-3">
                  <ColSelect label="Date column *" value={mapping.date} headers={preview.headers}
                    onChange={v => setMapping(m => m ? { ...m, date: v } : m)} />
                  <ColSelect label="Description column *" value={mapping.description} headers={preview.headers}
                    onChange={v => setMapping(m => m ? { ...m, description: v } : m)} />

                  {isSplit ? (
                    <>
                      <ColSelect label="Debit column (money out)" value={mapping.debit ?? ""} headers={["", ...preview.headers]}
                        onChange={v => setMapping(m => m ? { ...m, debit: v || null } : m)} />
                      <ColSelect label="Credit column (money in)" value={mapping.credit ?? ""} headers={["", ...preview.headers]}
                        onChange={v => setMapping(m => m ? { ...m, credit: v || null } : m)} />
                    </>
                  ) : (
                    <ColSelect label="Amount column *" value={mapping.amount ?? ""} headers={preview.headers}
                      onChange={v => setMapping(m => m ? { ...m, amount: v || null } : m)} />
                  )}

                  <div className="flex items-end gap-2">
                    <label className="flex items-center gap-2 text-sm cursor-pointer select-none">
                      <input
                        type="checkbox"
                        checked={isSplit}
                        onChange={e => {
                          if (e.target.checked) {
                            setMapping(m => m ? { ...m, amount: null, debit: preview.headers[0] ?? "", credit: preview.headers[1] ?? "" } : m);
                          } else {
                            setMapping(m => m ? { ...m, debit: null, credit: null, amount: preview.headers[0] ?? "" } : m);
                          }
                        }}
                        className="rounded"
                      />
                      Separate debit/credit columns
                    </label>
                  </div>
                </div>
              </div>

              {/* Preview table */}
              <div>
                <p className="text-sm font-semibold mb-2">Preview (first {preview.preview.length} rows)</p>
                <div className="overflow-x-auto rounded-lg border border-border">
                  <table className="w-full text-xs">
                    <thead className="bg-secondary/40">
                      <tr>
                        <th className="text-left px-3 py-2 text-muted-foreground font-medium">Date</th>
                        <th className="text-left px-3 py-2 text-muted-foreground font-medium">Description</th>
                        <th className="text-right px-3 py-2 text-muted-foreground font-medium">Amount</th>
                      </tr>
                    </thead>
                    <tbody>
                      {preview.preview.map((row, i) => (
                        <tr key={i} className="border-t border-border/50">
                          <td className="px-3 py-2 text-muted-foreground">{row.date_raw}</td>
                          <td className="px-3 py-2 truncate max-w-xs">{row.description_raw}</td>
                          <td className={cn("px-3 py-2 text-right tabular-nums font-medium",
                            row.amount_raw == null ? "text-muted-foreground" :
                            row.amount_raw >= 0 ? "text-success" : "text-destructive"
                          )}>
                            {row.amount_raw != null ? formatCurrency(row.amount_raw, "GBP") : "—"}
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              </div>

              {importMutation.isError && (
                <p className="text-destructive text-sm bg-destructive/10 rounded-md px-3 py-2">
                  {(importMutation.error as any)?.response?.data?.detail ?? "Import failed"}
                </p>
              )}

              <div className="flex gap-3">
                <button onClick={() => { setStep("upload"); setFile(null); setPreview(null); }}
                  className="flex-1 border border-border rounded-lg py-2.5 text-sm hover:bg-secondary transition-colors">
                  Back
                </button>
                <button
                  onClick={() => importMutation.mutate()}
                  disabled={importMutation.isPending || !mapping.date || !mapping.description || (!isSplit && !mapping.amount) || (isSplit && (!mapping.debit || !mapping.credit))}
                  className="flex-1 flex items-center justify-center gap-2 bg-primary text-primary-foreground rounded-lg py-2.5 text-sm font-medium hover:bg-primary/90 disabled:opacity-50 transition-colors"
                >
                  {importMutation.isPending ? <><Loader2 className="w-4 h-4 animate-spin" /> Importing…</> : `Import ${preview.total_rows} rows`}
                </button>
              </div>
            </>
          )}

          {/* Step: done */}
          {step === "done" && result && (
            <div className="text-center py-8 space-y-4">
              <CheckCircle className="w-14 h-14 text-success mx-auto" />
              <div>
                <p className="text-xl font-bold">{result.imported} transaction{result.imported !== 1 ? "s" : ""} imported</p>
                {result.skipped > 0 && (
                  <p className="text-sm text-muted-foreground mt-1">{result.skipped} duplicate{result.skipped !== 1 ? "s" : ""} skipped</p>
                )}
              </div>
              <div className="flex gap-3 justify-center">
                <button onClick={() => { setStep("upload"); setFile(null); setPreview(null); setResult(null); }}
                  className="border border-border rounded-lg px-5 py-2 text-sm hover:bg-secondary transition-colors">
                  Import another
                </button>
                <button onClick={onClose}
                  className="bg-primary text-primary-foreground rounded-lg px-5 py-2 text-sm font-medium hover:bg-primary/90 transition-colors">
                  Done
                </button>
              </div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function ColSelect({ label, value, headers, onChange }: {
  label: string; value: string; headers: string[]; onChange: (v: string) => void;
}) {
  return (
    <div>
      <label className="text-xs text-muted-foreground block mb-1">{label}</label>
      <select
        value={value}
        onChange={e => onChange(e.target.value)}
        className="w-full rounded-md border border-input bg-background px-2 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
      >
        {headers.map(h => <option key={h} value={h}>{h || "— none —"}</option>)}
      </select>
    </div>
  );
}

