import { ReactNode, useMemo, useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { Link } from "@inertiajs/react";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { CreditCard, TrendingDown, AlertTriangle, Wallet, Building2, ExternalLink, ArrowDown, ArrowUp, CheckCircle2, FileText, Search } from "lucide-react";
import { formatDistanceToNowStrict, format } from "date-fns";
import { toast } from "sonner";
import { useAuth } from "@/hooks/useAuth";

const csrfToken = () =>
  (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement | null)?.content ?? '';

interface CompanyRow {
  id: string;
  name: string;
  paymentTermsDays: number;
  creditLimitCents: number;
  outstandingCents: number;
  overdueCents: number;
  availableCents: number;
  utilizationPercent: number;
  outstandingCount: number;
  overdueCount: number;
  oldestOverdueDate: string | null;
}

interface OverviewResponse {
  totals: {
    totalCreditLimitCents: number;
    totalOutstandingCents: number;
    totalOverdueCents: number;
    totalAvailableCents: number;
    companiesOnCredit: number;
    companiesOverdue: number;
    totalOutstandingCount: number;
    totalOverdueCount: number;
  };
  companies: CompanyRow[];
}

interface OutstandingInvoice {
  id: string;
  company_id: string | null;
  company_name: string | null;
  course_title: string | null;
  customer_name: string;
  customer_email: string;
  start_date: string;
  created_at: string;
  due_date: string;
  is_overdue: boolean;
  days_overdue: number;
  unpaid_cents: number;
  status: string;
  payment_method: string;
}

interface OutstandingInvoicesResponse {
  invoices: OutstandingInvoice[];
  total_unpaid_cents: number;
  count: number;
  overdue_count: number;
}

type SortKey = "name" | "utilizationPercent" | "outstandingCents" | "overdueCents" | "availableCents";

const fmtMoney = (cents: number) =>
  `£${(cents / 100).toLocaleString("en-GB", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;

export const FinanceOverview = () => {
  const queryClient = useQueryClient();
  // Settling an invoice is restricted to sys_admin / sys_manager (matches the
  // API gate) — legacy admin/manager staff can view but not mark paid.
  const { hasAnyRole } = useAuth();
  const canMarkPaid = hasAnyRole(["sys_admin", "sys_manager"]);
  const { data, isLoading, error } = useQuery<OverviewResponse>({
    queryKey: ["finance-overview"],
    queryFn: async () => {
      const res = await fetch("/api/admin/finance/overview");
      if (!res.ok) throw new Error("Failed to load finance overview");
      return res.json();
    },
  });

  const { data: invoiceData, isLoading: invoicesLoading } = useQuery<OutstandingInvoicesResponse>({
    queryKey: ["finance-outstanding-invoices"],
    queryFn: async () => {
      const res = await fetch("/api/admin/finance/outstanding-invoices");
      if (!res.ok) throw new Error("Failed to load outstanding invoices");
      return res.json();
    },
  });

  const markPaidMutation = useMutation({
    mutationFn: async (orderId: string) => {
      const res = await fetch(`/api/admin/orders/${orderId}/mark-paid`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken() },
        body: JSON.stringify({}),
      });
      if (!res.ok) {
        const err = await res.json().catch(() => ({ error: 'Failed' }));
        throw new Error(err.error || 'Failed to mark paid');
      }
      return res.json();
    },
    onSuccess: () => {
      toast.success("Invoice marked as paid");
      queryClient.invalidateQueries({ queryKey: ["finance-outstanding-invoices"] });
      queryClient.invalidateQueries({ queryKey: ["finance-overview"] });
      queryClient.invalidateQueries({ queryKey: ["company-credit-orders"] });
      queryClient.invalidateQueries({ queryKey: ["admin-orders"] });
    },
    onError: (err: Error) => toast.error(err.message || "Failed to mark paid"),
  });

  const [sortKey, setSortKey] = useState<SortKey>("overdueCents");
  const [sortDir, setSortDir] = useState<"asc" | "desc">("desc");
  const [invoiceSearch, setInvoiceSearch] = useState("");
  const [showOverdueOnly, setShowOverdueOnly] = useState(false);

  const filteredInvoices = useMemo(() => {
    if (!invoiceData?.invoices) return [];
    return invoiceData.invoices.filter((inv) => {
      if (showOverdueOnly && !inv.is_overdue) return false;
      if (!invoiceSearch.trim()) return true;
      const s = invoiceSearch.toLowerCase();
      return (
        inv.company_name?.toLowerCase().includes(s) ||
        inv.course_title?.toLowerCase().includes(s) ||
        inv.customer_name?.toLowerCase().includes(s) ||
        inv.customer_email?.toLowerCase().includes(s) ||
        inv.id.toLowerCase().includes(s)
      );
    });
  }, [invoiceData, invoiceSearch, showOverdueOnly]);

  const sorted = useMemo(() => {
    if (!data?.companies) return [];
    const rows = [...data.companies];
    rows.sort((a, b) => {
      const av = a[sortKey];
      const bv = b[sortKey];
      if (typeof av === "string" && typeof bv === "string") {
        return sortDir === "asc" ? av.localeCompare(bv) : bv.localeCompare(av);
      }
      return sortDir === "asc" ? Number(av) - Number(bv) : Number(bv) - Number(av);
    });
    return rows;
  }, [data, sortKey, sortDir]);

  const toggleSort = (key: SortKey) => {
    if (sortKey === key) {
      setSortDir((d) => (d === "asc" ? "desc" : "asc"));
    } else {
      setSortKey(key);
      setSortDir(key === "name" ? "asc" : "desc");
    }
  };

  if (isLoading) {
    return <p className="text-muted-foreground">Loading finance overview…</p>;
  }
  if (error || !data) {
    return <p className="text-destructive">Could not load finance overview.</p>;
  }

  const t = data.totals;

  return (
    <div className="space-y-6">
      <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
        <KpiCard
          icon={<CreditCard className="h-4 w-4 text-muted-foreground" />}
          label="Total Credit Extended"
          value={fmtMoney(t.totalCreditLimitCents)}
          sub={`${t.companiesOnCredit} compan${t.companiesOnCredit === 1 ? "y" : "ies"}`}
        />
        <KpiCard
          icon={<TrendingDown className="h-4 w-4 text-muted-foreground" />}
          label="Outstanding"
          value={fmtMoney(t.totalOutstandingCents)}
          sub={`${t.totalOutstandingCount} invoice${t.totalOutstandingCount === 1 ? "" : "s"}`}
        />
        <KpiCard
          icon={<AlertTriangle className="h-4 w-4 text-muted-foreground" />}
          label="Overdue"
          value={fmtMoney(t.totalOverdueCents)}
          sub={`${t.totalOverdueCount} invoice${t.totalOverdueCount === 1 ? "" : "s"} • ${t.companiesOverdue} compan${t.companiesOverdue === 1 ? "y" : "ies"}`}
          valueClass={t.totalOverdueCents > 0 ? "text-destructive" : ""}
        />
        <KpiCard
          icon={<Wallet className="h-4 w-4 text-muted-foreground" />}
          label="Available Aggregate"
          value={fmtMoney(t.totalAvailableCents)}
        />
      </div>

      <div className="bg-card border border-border rounded-xl overflow-hidden">
        <div className="px-4 py-3 border-b border-border flex items-center justify-between">
          <h2 className="text-lg font-semibold text-primary flex items-center gap-2">
            <Building2 className="h-4 w-4" /> Companies on Credit ({t.companiesOnCredit})
          </h2>
        </div>
        {sorted.length === 0 ? (
          <p className="text-muted-foreground text-center py-8">No companies on credit terms.</p>
        ) : (
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>
                  <SortHeader label="Company" active={sortKey === "name"} dir={sortDir} onClick={() => toggleSort("name")} />
                </TableHead>
                <TableHead>
                  <SortHeader label="Utilisation" active={sortKey === "utilizationPercent"} dir={sortDir} onClick={() => toggleSort("utilizationPercent")} />
                </TableHead>
                <TableHead>Limit</TableHead>
                <TableHead>
                  <SortHeader label="Outstanding" active={sortKey === "outstandingCents"} dir={sortDir} onClick={() => toggleSort("outstandingCents")} />
                </TableHead>
                <TableHead>
                  <SortHeader label="Overdue" active={sortKey === "overdueCents"} dir={sortDir} onClick={() => toggleSort("overdueCents")} />
                </TableHead>
                <TableHead>
                  <SortHeader label="Available" active={sortKey === "availableCents"} dir={sortDir} onClick={() => toggleSort("availableCents")} />
                </TableHead>
                <TableHead>Oldest Overdue</TableHead>
                <TableHead className="text-right">Actions</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {sorted.map((c) => (
                <TableRow key={c.id}>
                  <TableCell className="font-medium">{c.name}</TableCell>
                  <TableCell className="min-w-[160px]">
                    <div className="flex items-center gap-2">
                      <span className={c.utilizationPercent >= 90 ? "text-destructive font-semibold" : ""}>
                        {c.utilizationPercent}%
                      </span>
                      <div className="flex-1 h-2 bg-muted rounded-full overflow-hidden">
                        <div
                          className={`h-full rounded-full ${
                            c.utilizationPercent >= 90 ? "bg-destructive" : c.utilizationPercent >= 70 ? "bg-yellow-500" : "bg-primary"
                          }`}
                          style={{ width: `${Math.min(c.utilizationPercent, 100)}%` }}
                        />
                      </div>
                    </div>
                  </TableCell>
                  <TableCell>{fmtMoney(c.creditLimitCents)}</TableCell>
                  <TableCell>
                    {fmtMoney(c.outstandingCents)}
                    {c.outstandingCount > 0 && (
                      <span className="text-muted-foreground text-xs ml-1">({c.outstandingCount})</span>
                    )}
                  </TableCell>
                  <TableCell>
                    {c.overdueCents > 0 ? (
                      <span className="text-destructive font-semibold inline-flex items-center">
                        {fmtMoney(c.overdueCents)}
                        <Badge variant="destructive" className="ml-2 text-xs">{c.overdueCount}</Badge>
                      </span>
                    ) : (
                      <span className="text-muted-foreground">—</span>
                    )}
                  </TableCell>
                  <TableCell className={c.availableCents <= 0 ? "text-destructive" : ""}>
                    {fmtMoney(c.availableCents)}
                  </TableCell>
                  <TableCell className="text-sm">
                    {c.oldestOverdueDate ? (
                      <span className="text-destructive">
                        {formatDistanceToNowStrict(new Date(c.oldestOverdueDate), { addSuffix: true })}
                      </span>
                    ) : (
                      <span className="text-muted-foreground">—</span>
                    )}
                  </TableCell>
                  <TableCell className="text-right">
                    <Link href={`/admin/companies/${c.id}`}>
                      <Button variant="outline" size="sm" className="h-7 text-xs">
                        View <ExternalLink className="ml-1 h-3 w-3" />
                      </Button>
                    </Link>
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        )}
      </div>

      {/* Outstanding invoices reconciliation panel */}
      <div className="bg-card border border-border rounded-xl overflow-hidden">
        <div className="px-4 py-3 border-b border-border flex items-center justify-between flex-wrap gap-3">
          <h2 className="text-lg font-semibold text-primary flex items-center gap-2">
            <FileText className="h-4 w-4" /> Outstanding Invoices
            {invoiceData && (
              <span className="text-sm font-normal text-muted-foreground">
                ({invoiceData.count} unpaid · {fmtMoney(invoiceData.total_unpaid_cents)})
              </span>
            )}
          </h2>
          <div className="flex items-center gap-2">
            <div className="relative">
              <Search className="absolute left-2 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground" />
              <Input
                placeholder="Search invoices…"
                value={invoiceSearch}
                onChange={(e) => setInvoiceSearch(e.target.value)}
                className="pl-7 h-8 text-xs w-[220px]"
              />
            </div>
            <Button
              variant={showOverdueOnly ? "default" : "outline"}
              size="sm"
              className="h-8 text-xs"
              onClick={() => setShowOverdueOnly((v) => !v)}
            >
              <AlertTriangle className="w-3.5 h-3.5 mr-1" />
              Overdue only
              {invoiceData && invoiceData.overdue_count > 0 && (
                <Badge variant="destructive" className="ml-1.5 text-[10px] h-4 px-1.5">{invoiceData.overdue_count}</Badge>
              )}
            </Button>
          </div>
        </div>
        {invoicesLoading ? (
          <p className="text-muted-foreground p-6">Loading outstanding invoices…</p>
        ) : filteredInvoices.length === 0 ? (
          <p className="text-muted-foreground text-center py-8">
            {invoiceData?.count === 0
              ? "No outstanding invoices — all settled."
              : "No invoices match the current filter."}
          </p>
        ) : (
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Order Date</TableHead>
                <TableHead>Company</TableHead>
                <TableHead>Course</TableHead>
                <TableHead>Customer</TableHead>
                <TableHead>Due</TableHead>
                <TableHead className="text-right">Unpaid</TableHead>
                {canMarkPaid && <TableHead className="text-right">Actions</TableHead>}
              </TableRow>
            </TableHeader>
            <TableBody>
              {filteredInvoices.map((inv) => {
                const pending = markPaidMutation.isPending && markPaidMutation.variables === inv.id;
                return (
                  <TableRow key={inv.id}>
                    <TableCell className="text-xs whitespace-nowrap">
                      {format(new Date(inv.created_at), "dd MMM yy")}
                    </TableCell>
                    <TableCell className="font-medium">
                      {inv.company_id ? (
                        <Link href={`/admin/companies/${inv.company_id}`} className="hover:underline">
                          {inv.company_name || "—"}
                        </Link>
                      ) : (
                        inv.company_name || "—"
                      )}
                    </TableCell>
                    <TableCell className="max-w-[200px] truncate">{inv.course_title || "—"}</TableCell>
                    <TableCell className="text-xs">
                      <div>{inv.customer_name}</div>
                      <div className="text-muted-foreground">{inv.customer_email}</div>
                    </TableCell>
                    <TableCell className="text-xs whitespace-nowrap">
                      <span className={inv.is_overdue ? "text-destructive font-semibold" : ""}>
                        {format(new Date(inv.due_date), "dd MMM yy")}
                      </span>
                      {inv.is_overdue && (
                        <Badge variant="destructive" className="ml-1.5 text-[10px] h-4 px-1.5">
                          {inv.days_overdue}d
                        </Badge>
                      )}
                    </TableCell>
                    <TableCell className="text-right font-semibold whitespace-nowrap">
                      {fmtMoney(inv.unpaid_cents)}
                    </TableCell>
                    {canMarkPaid && (
                      <TableCell className="text-right">
                        <Button
                          size="sm"
                          variant="outline"
                          className="h-7 text-xs"
                          disabled={pending}
                          onClick={() => markPaidMutation.mutate(inv.id)}
                        >
                          <CheckCircle2 className="w-3.5 h-3.5 mr-1" />
                          {pending ? "Marking…" : "Mark Paid"}
                        </Button>
                      </TableCell>
                    )}
                  </TableRow>
                );
              })}
            </TableBody>
          </Table>
        )}
      </div>
    </div>
  );
};

const KpiCard = ({
  icon,
  label,
  value,
  sub,
  valueClass,
}: {
  icon: ReactNode;
  label: string;
  value: string;
  sub?: string;
  valueClass?: string;
}) => (
  <div className="bg-card border border-border rounded-xl p-4">
    <div className="flex items-center gap-2 mb-1">
      {icon}
      <p className="text-sm text-muted-foreground">{label}</p>
    </div>
    <p className={`text-2xl font-bold text-foreground ${valueClass ?? ""}`}>{value}</p>
    {sub && <p className="text-xs text-muted-foreground mt-1">{sub}</p>}
  </div>
);

const SortHeader = ({
  label,
  active,
  dir,
  onClick,
}: {
  label: string;
  active: boolean;
  dir: "asc" | "desc";
  onClick: () => void;
}) => (
  <button onClick={onClick} className="flex items-center gap-1 hover:text-foreground transition-colors">
    {label}
    {active && (dir === "asc" ? <ArrowUp className="h-3 w-3" /> : <ArrowDown className="h-3 w-3" />)}
  </button>
);
