import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useServerFn } from "@tanstack/react-start";
import { useState, useEffect, useMemo, useRef } from "react";
import { toast } from "sonner";
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 { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
import { listNigerianBanks, verifyAccountName, initiateTransfer } from "@/lib/flutterwave.functions";
import { getWalletAndProfile } from "@/lib/wallet.functions";
import { lookupUserByTag, previewInternalFee, internalTransfer } from "@/lib/internal-transfer.functions";
import { formatNaira } from "@/lib/format";
import { Money } from "@/components/Money";
import { Send, Building2, AtSign } from "lucide-react";
import { PinPromptDialog } from "@/components/PinPromptDialog";

export const Route = createFileRoute("/app/transfer")({
  head: () => ({ meta: [{ title: "Transfer — Billsline" }] }),
  validateSearch: (search: Record<string, unknown>) => {
    const tag = typeof search.tag === "string" ? search.tag.replace(/^@/, "").toLowerCase() : undefined;
    const amount = Number(search.amount);
    return {
      ...(tag && /^[a-z0-9_]{3,32}$/.test(tag) ? { tag } : {}),
      ...(Number.isFinite(amount) && amount > 0 ? { amount } : {}),
    };
  },
  component: TransferPage,
});

function TransferPage() {
  const fetchWP = useServerFn(getWalletAndProfile);
  const { data: wp } = useQuery({ queryKey: ["wallet"], queryFn: () => fetchWP() });

  return (
    <div className="space-y-4 p-4">
      <header className="flex items-center justify-between">
        <h1 className="text-xl font-bold text-primary">Send money</h1>
        <span className="text-xs text-muted-foreground">Balance: <Money value={wp?.wallet?.balance ?? 0} /></span>
      </header>

      <Tabs defaultValue="internal">
        <TabsList className="grid w-full grid-cols-2">
          <TabsTrigger value="internal"><AtSign className="mr-1.5 h-4 w-4" />Billsline</TabsTrigger>
          <TabsTrigger value="bank"><Building2 className="mr-1.5 h-4 w-4" />Bank</TabsTrigger>
        </TabsList>
        <TabsContent value="internal" className="mt-3"><InternalTransfer /></TabsContent>
        <TabsContent value="bank" className="mt-3"><BankTransfer /></TabsContent>
      </Tabs>
    </div>
  );
}

function InternalTransfer() {
  const qc = useQueryClient();
  const navigate = useNavigate();
  const lookup = useServerFn(lookupUserByTag);
  const preview = useServerFn(previewInternalFee);
  const send = useServerFn(internalTransfer);

  const search = Route.useSearch();
  const [tag, setTag] = useState(search.tag ?? "");
  const [amount, setAmount] = useState(search.amount ?? 1000);
  const [narration, setNarration] = useState("");
  const [pin, setPin] = useState("");
  const [pinOpen, setPinOpen] = useState(false);
  const [recipient, setRecipient] = useState<{ id: string; username: string | null; full_name: string | null; avatar_url: string | null } | null>(null);
  const [fee, setFee] = useState<{ fee: number; total: number; min: number; max: number; enabled: boolean } | null>(null);

  // Fee preview (debounced)
  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 lookupM = useMutation({
    mutationFn: () => lookup({ data: { tag } }),
    onSuccess: (r) => {
      if (!r.ok) { setRecipient(null); toast.error(r.error); return; }
      setRecipient(r.user); toast.success(`@${r.user.username} found`);
    },
    onError: (e: Error) => { setRecipient(null); toast.error(e.message); },
  });

  const prefilled = useRef(false);
  useEffect(() => {
    if (prefilled.current || !search.tag) return;
    prefilled.current = true;
    lookupM.mutate();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [search.tag]);

  const submit = useMutation({
    mutationFn: (authPin?: string) =>
      send({ data: { recipient_tag: tag, amount, narration, pin: authPin || pin || undefined } }),
    onSuccess: (r: unknown) => {
      qc.invalidateQueries();
      const ref = (r as { reference?: string })?.reference;
      setTag(""); setRecipient(null); setNarration(""); setPin("");
      if (ref) navigate({ to: "/app/tx/$ref", params: { ref } });
      else toast.success("Transfer successful");
    },
    onError: (e: Error) => toast.error(e.message),
  });

  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">Billsline transfers are temporarily disabled.</div>
      )}
      <div>
        <Label>Recipient @tag</Label>
        <div className="mt-1 flex gap-2">
          <div className="flex flex-1 items-center rounded-md border border-input bg-background pl-2">
            <AtSign className="h-4 w-4 text-muted-foreground" />
            <Input value={tag} onChange={(e) => { setTag(e.target.value.replace(/^@/, "")); setRecipient(null); }}
              placeholder="username" className="border-0 px-1 focus-visible:ring-0" />
          </div>
          <Button variant="outline" disabled={tag.length < 3 || lookupM.isPending} onClick={() => lookupM.mutate()}>
            {lookupM.isPending ? "…" : "Find"}
          </Button>
        </div>
      </div>

      {recipient && (
        <div className="flex items-center gap-3 rounded-lg bg-success/10 p-3">
          <Avatar className="h-10 w-10">
            <AvatarImage src={recipient.avatar_url ?? undefined} />
            <AvatarFallback>{(recipient.full_name ?? recipient.username ?? "?").slice(0, 2).toUpperCase()}</AvatarFallback>
          </Avatar>
          <div>
            <div className="font-medium">{recipient.full_name ?? "Billsline user"}</div>
            <div className="text-xs text-muted-foreground">@{recipient.username}</div>
          </div>
        </div>
      )}

      <div>
        <Label>Amount (₦)</Label>
        <Input type="number" min={fee?.min ?? 50} max={fee?.max ?? 500_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="Amount" value={formatNaira(amount)} />
          <Row label="Fee" value={formatNaira(fee.fee)} />
          <Row label="Total debit" value={formatNaira(fee.total)} bold />
        </div>
      )}

      <div>
        <Label>Note (optional)</Label>
        <Input value={narration} onChange={(e) => setNarration(e.target.value)} placeholder="What's it for?" maxLength={140} />
      </div>

      <Button className="w-full bg-gradient-primary" disabled={!recipient || submit.isPending || !fee?.enabled} onClick={() => setPinOpen(true)}>
        <Send className="mr-2 h-4 w-4" />
        {submit.isPending ? "Sending…" : `Send ${formatNaira(amount)}`}
      </Button>

      <PinPromptDialog
        open={pinOpen}
        onOpenChange={setPinOpen}
        title="Confirm transfer"
        description="Enter your 4-digit PIN to authorize this transfer."
        amount={fee?.total ?? amount}
        summary={[
          { label: "Service", value: "Billsline transfer" },
          { label: "Recipient", value: recipient?.full_name ?? "—" },
          { label: "Tag", value: `@${recipient?.username ?? tag}` },
          { label: "Amount", value: formatNaira(amount) },
          { label: "Fee", value: formatNaira(fee?.fee ?? 0) },
          ...(narration ? [{ label: "Note", value: narration }] : []),
        ]}
        onVerified={(p) => { setPin(p); submit.mutate(p); }}
      />
    </div>
  );
}

function Row({ label, value, bold }: { label: string; value: string; bold?: boolean }) {
  return (
    <div className={`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>
  );
}

function BankTransfer() {
  const qc = useQueryClient();
  const fetchBanks = useServerFn(listNigerianBanks);
  const verify = useServerFn(verifyAccountName);
  const send = useServerFn(initiateTransfer);
  const { data: banks } = useQuery({ queryKey: ["banks"], queryFn: () => fetchBanks(), staleTime: 24 * 3600_000 });

  const [bank, setBank] = useState("");
  const [bankSearch, setBankSearch] = useState("");
  const [account, setAccount] = useState("");
  const [amount, setAmount] = useState(1000);
  const [narration, setNarration] = useState("");
  const [resolvedName, setResolvedName] = useState<string | null>(null);
  const [pinOpen, setPinOpen] = useState(false);

  const sortedBanks = useMemo(() => {
    const list = (banks ?? []).slice().sort((a: { name: string }, b: { name: string }) =>
      a.name.localeCompare(b.name, undefined, { sensitivity: "base" }),
    );
    const q = bankSearch.trim().toLowerCase();
    return q ? list.filter((b) => b.name.toLowerCase().includes(q)) : list;
  }, [banks, bankSearch]);

  const resolve = useMutation({
    mutationFn: () => verify({ data: { account_bank: bank, account_number: account } }),
    onSuccess: (r) => { setResolvedName(r.account_name); toast.success(r.account_name); },
    onError: (e: Error) => toast.error(e.message),
  });


  const submit = useMutation({
    mutationFn: () => send({ data: { account_bank: bank, account_number: account, amount, narration } }),
    onSuccess: () => { toast.success("Transfer initiated"); qc.invalidateQueries(); },
    onError: (e: Error) => toast.error(e.message),
  });

  return (
    <div className="space-y-3 rounded-2xl bg-card p-4 shadow-card">
      <div>
        <Label>Bank</Label>
        <Input
          placeholder="Search banks…"
          value={bankSearch}
          onChange={(e) => setBankSearch(e.target.value)}
          className="mt-1 mb-2"
        />
        <select className="h-10 w-full rounded-md border border-input bg-background px-3 text-sm"
          value={bank} onChange={(e) => { setBank(e.target.value); setResolvedName(null); }}>
          <option value="">Select bank ({sortedBanks.length})</option>
          {sortedBanks.map((b) => <option key={b.code} value={b.code}>{b.name}</option>)}
        </select>
      </div>
      <div>
        <Label>Account number</Label>
        <Input inputMode="numeric" maxLength={10} value={account}
          onChange={(e) => { setAccount(e.target.value); setResolvedName(null); }} />
      </div>
      {resolvedName && <div className="rounded-md bg-success/10 px-3 py-2 text-sm">{resolvedName}</div>}
      <Button variant="outline" disabled={!bank || account.length !== 10 || resolve.isPending} onClick={() => resolve.mutate()}>
        {resolve.isPending ? "Verifying…" : "Verify name"}
      </Button>
      <div>
        <Label>Amount</Label>
        <Input type="number" min={100} max={1000000} value={amount} onChange={(e) => setAmount(Number(e.target.value))} />
      </div>
      <div>
        <Label>Narration</Label>
        <Input value={narration} onChange={(e) => setNarration(e.target.value)} />
      </div>
      <Button className="w-full bg-gradient-primary" disabled={!resolvedName || submit.isPending} onClick={() => setPinOpen(true)}>
        {submit.isPending ? "Sending…" : `Send ${formatNaira(amount)}`}
      </Button>

      <PinPromptDialog
        open={pinOpen}
        onOpenChange={setPinOpen}
        title="Confirm bank transfer"
        description="Enter your 4-digit PIN to authorize this bank transfer."
        amount={amount}
        summary={[
          { label: "Service", value: "Bank transfer" },
          { label: "Bank", value: (banks ?? []).find((b) => b.code === bank)?.name ?? bank },
          { label: "Account number", value: account },
          { label: "Account name", value: resolvedName ?? "—" },
          ...(narration ? [{ label: "Narration", value: narration }] : []),
          { label: "Paid from", value: "Billsline Wallet" },
        ]}
        onVerified={() => submit.mutate()}
      />
    </div>
  );
}
