import { createFileRoute, Link } from "@tanstack/react-router";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useServerFn } from "@tanstack/react-start";
import { useEffect, useState } from "react";
import { toast } from "sonner";
import { Banknote, Building2, MapPin, Search, ShieldCheck, X } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
import { PinPromptDialog } from "@/components/PinPromptDialog";
import { formatNaira, formatDate } from "@/lib/format";
import {
  listAgents,
  previewWithdrawalFee,
  requestAgentWithdrawal,
  myWithdrawals,
  cancelWithdrawal,
} from "@/lib/withdrawals.functions";
import { cn } from "@/lib/utils";

export const Route = createFileRoute("/app/withdraw")({
  head: () => ({
    meta: [
      { title: "Withdraw cash — Billsline" },
      { name: "description", content: "Withdraw cash from your Billsline wallet through a nearby Billsline Agent, or send it to any Nigerian bank account." },
      { property: "og:title", content: "Withdraw cash — Billsline" },
      { property: "og:description", content: "Cash out at a Billsline Agent or transfer straight to your bank." },
      { property: "og:type", content: "website" },
      { name: "twitter:card", content: "summary" },
    ],
  }),
  component: WithdrawPage,
});

type Agent = {
  id: string;
  business_name: string;
  phone: string;
  city: string | null;
  state: string | null;
  address: string | null;
};

function WithdrawPage() {
  return (
    <div className="space-y-4 p-4 pb-10">
      <header>
        <h1 className="text-xl font-bold">Withdraw cash</h1>
        <p className="text-xs text-muted-foreground">Collect physical cash from a Billsline Agent, or move money to your bank.</p>
      </header>

      <Tabs defaultValue="agent">
        <TabsList className="grid w-full grid-cols-2">
          <TabsTrigger value="agent"><Banknote className="mr-1.5 h-4 w-4" />Agent cash</TabsTrigger>
          <TabsTrigger value="bank"><Building2 className="mr-1.5 h-4 w-4" />Bank</TabsTrigger>
        </TabsList>

        <TabsContent value="agent" className="mt-3 space-y-4">
          <AgentWithdraw />
          <History />
        </TabsContent>

        <TabsContent value="bank" className="mt-3">
          <div className="space-y-3 rounded-2xl bg-card p-4 shadow-card">
            <p className="text-sm text-muted-foreground">
              Send money straight from your wallet to any Nigerian bank account. Name verification and PIN
              authorisation are required, and failed payouts are refunded automatically.
            </p>
            <Button asChild className="w-full bg-gradient-primary">
              <Link to="/app/transfer">Go to bank transfer</Link>
            </Button>
          </div>
        </TabsContent>
      </Tabs>
    </div>
  );
}

function AgentWithdraw() {
  const qc = useQueryClient();
  const fetchAgents = useServerFn(listAgents);
  const preview = useServerFn(previewWithdrawalFee);
  const request = useServerFn(requestAgentWithdrawal);

  const [q, setQ] = useState("");
  const [agent, setAgent] = useState<Agent | null>(null);
  const [amount, setAmount] = useState(2000);
  const [fee, setFee] = useState<{ fee: number; total: number; min: number; max: number; enabled: boolean } | null>(null);
  const [pinOpen, setPinOpen] = useState(false);
  const [code, setCode] = useState<string | null>(null);

  const { data: agents = [] } = useQuery({
    queryKey: ["agents", q],
    queryFn: () => fetchAgents({ data: { q: q || undefined } }) as Promise<Agent[]>,
  });

  useEffect(() => {
    if (amount <= 0) { setFee(null); return; }
    const t = setTimeout(() => { preview({ data: { amount } }).then(setFee).catch(() => setFee(null)); }, 250);
    return () => clearTimeout(t);
  }, [amount, preview]);

  const submit = useMutation({
    mutationFn: (pin: string) => request({ data: { agent_id: agent!.id, amount, pin } }),
    onSuccess: (r) => {
      setCode(r.code);
      setAgent(null);
      qc.invalidateQueries();
    },
    onError: (e: Error) => toast.error(e.message),
  });

  if (code) {
    return (
      <div className="space-y-3 rounded-2xl bg-card p-5 text-center shadow-card ring-1 ring-success/30">
        <ShieldCheck className="mx-auto h-10 w-10 text-success" />
        <h2 className="text-base font-bold">Show this code to the agent</h2>
        <p className="text-4xl font-black tracking-[0.35em] text-primary">{code}</p>
        <p className="text-xs text-muted-foreground">
          Your money is held safely. The agent is only paid after they enter this code — never share it before you
          receive your cash.
        </p>
        <Button variant="outline" className="w-full" onClick={() => setCode(null)}>Done</Button>
      </div>
    );
  }

  return (
    <div className="space-y-3 rounded-2xl bg-card p-4 shadow-card">
      {fee && !fee.enabled && (
        <div className="rounded-md bg-warning/10 px-3 py-2 text-sm text-warning">Agent withdrawals are temporarily disabled.</div>
      )}

      <div>
        <Label>Find an agent</Label>
        <div className="mt-1 flex items-center rounded-md border border-input bg-background pl-2">
          <Search className="h-4 w-4 text-muted-foreground" />
          <Input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Name, city or state"
            className="border-0 px-1 focus-visible:ring-0" />
        </div>
      </div>

      <ul className="max-h-64 space-y-2 overflow-y-auto">
        {agents.length === 0 && <li className="py-6 text-center text-xs text-muted-foreground">No agents found yet.</li>}
        {agents.map((a) => (
          <li key={a.id}>
            <button type="button" onClick={() => setAgent(a)}
              className={cn(
                "w-full rounded-xl border p-3 text-left transition",
                agent?.id === a.id ? "border-primary bg-primary/5" : "border-border/60 hover:bg-muted/40",
              )}>
              <div className="text-sm font-semibold">{a.business_name}</div>
              <div className="flex items-center gap-1 text-[11px] text-muted-foreground">
                <MapPin className="h-3 w-3" />{[a.address, a.city, a.state].filter(Boolean).join(", ") || "Nigeria"}
              </div>
              <div className="text-[11px] text-muted-foreground">{a.phone}</div>
            </button>
          </li>
        ))}
      </ul>

      <div>
        <Label>Amount (₦)</Label>
        <Input type="number" min={fee?.min ?? 500} max={fee?.max ?? 200_000} value={amount}
          onChange={(e) => setAmount(Number(e.target.value))} />
      </div>

      {fee && (
        <div className="rounded-lg bg-muted/50 p-3 text-xs">
          <Row label="Cash to collect" value={formatNaira(amount)} />
          <Row label="Service fee" value={formatNaira(fee.fee)} />
          <Row label="Total debit" value={formatNaira(fee.total)} bold />
        </div>
      )}

      <Button className="w-full bg-gradient-primary" disabled={!agent || submit.isPending || !fee?.enabled}
        onClick={() => setPinOpen(true)}>
        {submit.isPending ? "Processing…" : `Withdraw ${formatNaira(amount)}`}
      </Button>

      <PinPromptDialog
        open={pinOpen}
        onOpenChange={setPinOpen}
        title="Confirm withdrawal"
        description="Enter your 4-digit PIN to hold this cash for pickup."
        amount={fee?.total ?? amount}
        summary={[
          { label: "Service", value: "Agent cash withdrawal" },
          { label: "Agent", value: agent?.business_name ?? "—" },
          { label: "Location", value: [agent?.city, agent?.state].filter(Boolean).join(", ") || "—" },
          { label: "Cash", value: formatNaira(amount) },
          { label: "Fee", value: formatNaira(fee?.fee ?? 0) },
          { label: "Paid from", value: "Billsline Wallet" },
        ]}
        onVerified={(p) => submit.mutate(p)}
      />
    </div>
  );
}

function History() {
  const qc = useQueryClient();
  const list = useServerFn(myWithdrawals);
  const cancel = useServerFn(cancelWithdrawal);
  const { data = [] } = useQuery({ queryKey: ["withdrawals"], queryFn: () => list(), refetchInterval: 15_000 });
  const rows = data as unknown as Array<{
    id: string; amount: number; fee: number; status: string; reference: string;
    created_at: string; agents?: { business_name?: string } | null;
  }>;

  const cancelM = useMutation({
    mutationFn: (id: string) => cancel({ data: { id } }),
    onSuccess: () => { toast.success("Withdrawal cancelled — money returned"); qc.invalidateQueries(); },
    onError: (e: Error) => toast.error(e.message),
  });

  if (rows.length === 0) return null;

  return (
    <div className="space-y-2 rounded-2xl bg-card p-4 shadow-card">
      <h2 className="text-sm font-bold">Recent withdrawals</h2>
      <ul className="space-y-2">
        {rows.map((w) => (
          <li key={w.id} className="flex items-center justify-between rounded-xl bg-muted/40 p-3">
            <div className="min-w-0">
              <p className="truncate text-sm font-semibold">{formatNaira(Number(w.amount))}</p>
              <p className="truncate text-[11px] text-muted-foreground">
                {w.agents?.business_name ?? "Agent"} · {formatDate(w.created_at)}
              </p>
            </div>
            <div className="flex items-center gap-2">
              <span className={cn(
                "rounded-full px-2 py-0.5 text-[10px] font-semibold",
                w.status === "completed" ? "bg-success/15 text-success"
                  : w.status === "pending" ? "bg-warning/15 text-warning" : "bg-muted text-muted-foreground",
              )}>{w.status}</span>
              {w.status === "pending" && (
                <button onClick={() => cancelM.mutate(w.id)} aria-label="Cancel withdrawal"
                  className="rounded-full bg-destructive/10 p-1 text-destructive">
                  <X className="h-3.5 w-3.5" />
                </button>
              )}
            </div>
          </li>
        ))}
      </ul>
    </div>
  );
}

function Row({ label, value, bold }: { label: string; value: string; bold?: boolean }) {
  return (
    <div className={cn("flex items-center justify-between py-1", bold && "border-t border-border/60 pt-2 font-semibold")}>
      <span className="text-muted-foreground">{label}</span><span>{value}</span>
    </div>
  );
}
