import { useCallback, useEffect, useMemo, useState } from "react";
import { createFileRoute, Link } from "@tanstack/react-router";
import {
  ArrowLeft,
  Building2,
  FileStack,
  Landmark,
  Loader2,
  MessageSquareText,
  ShieldAlert,
  X,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { ActivityTimeline } from "@/components/ledger/ActivityTimeline";
import { ConfidenceIndicator } from "@/components/ledger/ConfidenceIndicator";
import { EmptyState, KpiCard, PageHeader, SectionCard } from "@/components/ledger/Primitives";
import { DuplicateBadge, Pill, StatusBadge } from "@/components/ledger/StatusBadge";
import { QueryPriorityBadge, queryStatusTone } from "@/components/ledger/QueryThread";
import { UserAvatar } from "@/components/auth/UserAvatar";
import { useAuthSession } from "@/hooks/useAuthSession";
import { fetchClientOverviewApi, type ClientOverviewResponse } from "@/lib/api";
import { eur, relativeTime } from "@/lib/ledger-store";
import type { InvoiceStatus } from "@/lib/ledger-types";
import { snelstartStatusLabel, snelstartStatusTone } from "@/lib/snelstart";
import { clientsListSearch } from "@app/lib/clients-search";
import { Route as ClientsRoute } from "./clients";

function ClientRouteError({ error, reset }: { error: Error; reset: () => void }) {
  const listSearch = ClientsRoute.useSearch();
  return (
    <SectionCard>
      <EmptyState
        icon={X}
        title="Unable to load this client."
        description={error.message || "Something went wrong while opening this client."}
        action={
          <div className="flex flex-wrap justify-center gap-2">
            <Button variant="outline" onClick={reset}>
              Try again
            </Button>
            <Button variant="ghost" asChild>
              <Link to="/clients" search={clientsListSearch(listSearch)}>
                ← Back to Clients
              </Link>
            </Button>
          </div>
        }
      />
    </SectionCard>
  );
}

export const Route = createFileRoute("/clients/$id")({
  head: () => ({
    meta: [{ title: "Client overview — Amanah" }],
  }),
  component: ClientDetailPage,
  errorComponent: ClientRouteError,
});

function ClientDetailPage() {
  const { id } = Route.useParams();
  const listSearch = ClientsRoute.useSearch();
  const session = useAuthSession("firm");
  const [data, setData] = useState<ClientOverviewResponse | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [statusCode, setStatusCode] = useState<number | null>(null);

  const load = useCallback(async () => {
    if (!session?.email) return;
    setLoading(true);
    setError(null);
    setStatusCode(null);
    try {
      const next = await fetchClientOverviewApi(id, { platform: "firm", email: session.email });
      setData(next);
    } catch (err) {
      setData(null);
      const message = err instanceof Error ? err.message : "Unable to load this client.";
      setError(message);
      const code = (err as Error & { status?: number }).status;
      setStatusCode(typeof code === "number" ? code : null);
    } finally {
      setLoading(false);
    }
  }, [id, session?.email]);

  useEffect(() => {
    void load();
  }, [load]);

  const operationalStatus = useMemo(() => {
    if (!data) return null;
    return data.kpis.openQueries > 0 ? "Awaiting client" : "In control";
  }, [data]);

  if (loading) {
    return (
      <div className="flex items-center gap-3 px-1 py-8 text-[13px] text-muted-foreground">
        <Loader2 size={16} className="animate-spin text-brand" aria-hidden="true" />
        Loading client...
      </div>
    );
  }

  if (error || !data) {
    const unauthorized = statusCode === 403;
    const missing = statusCode === 404;
    return (
      <SectionCard>
        <EmptyState
          icon={unauthorized ? ShieldAlert : missing ? Building2 : X}
          title={
            unauthorized ? "Access denied" : missing ? "Client not found" : "Unable to load this client."
          }
          description={
            unauthorized
              ? "You do not have access to this client."
              : missing
                ? "This client does not exist or is no longer available."
                : error ?? "Something went wrong while opening this client."
          }
          action={
            <div className="flex flex-wrap justify-center gap-2">
              {!unauthorized ? (
                <Button variant="outline" onClick={() => void load()}>
                  Try again
                </Button>
              ) : null}
              <Button variant="ghost" asChild>
                <Link to="/clients" search={clientsListSearch(listSearch)}>
                ← Back to Clients
              </Link>
              </Button>
            </div>
          }
        />
      </SectionCard>
    );
  }

  const { client, portal, snelstart, kpis, lastActivity } = data;
  const documents = data.documents ?? [];
  const queries = data.queries ?? [];
  const activity = data.activity ?? [];
  const bank = data.bank;
  const companyName = portal?.company || null;
  const email = client.email || portal?.email || "";
  const snelstartStatus = snelstart?.status || client.snelstartStatus || "not_connected";

  return (
    <div className="space-y-6">
      <PageHeader
        eyebrow="Clients"
        title={client.name}
        subtitle={companyName || email || "No portal email configured"}
        actions={
          <Button variant="outline" asChild>
            <Link to="/clients" search={clientsListSearch(listSearch)}>
              <ArrowLeft size={16} /> Back to Clients
            </Link>
          </Button>
        }
      />

      <div className="flex flex-wrap items-center gap-3">
        <UserAvatar name={portal?.name || client.name} avatarUrl={portal?.avatarUrl} size="lg" />
        <div className="min-w-0 flex-1">
          <div className="flex flex-wrap items-center gap-2">
            <Pill tone={kpis.openQueries > 0 ? "amber" : "neutral"}>{operationalStatus}</Pill>
            <Pill tone={snelstartStatusTone(snelstartStatus)}>
              SnelStart · {snelstartStatusLabel(snelstartStatus)}
            </Pill>
            {client.kvk ? <Pill tone="neutral">KvK {client.kvk}</Pill> : null}
          </div>
          <p className="mt-1.5 text-[13px] text-muted-foreground">
            {email ? email : "No portal email"}
            {companyName ? ` · ${companyName}` : ""}
          </p>
        </div>
      </div>

      <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
        <KpiCard label="Documents" value={kpis.documents} hint="Uploads for this client" icon={FileStack} />
        <KpiCard
          label="Needs review"
          value={kpis.needsReview}
          hint="In the review queue"
          icon={FileStack}
          tone={kpis.needsReview > 0 ? "amber" : "neutral"}
        />
        <KpiCard
          label="Open queries"
          value={kpis.openQueries}
          hint="Awaiting response or review"
          icon={MessageSquareText}
          tone={kpis.openQueries > 0 ? "amber" : "neutral"}
        />
        <KpiCard
          label="Matched transactions"
          value={kpis.matchedTransactions}
          hint="Bank matches for this client"
          icon={Landmark}
          tone={kpis.matchedTransactions > 0 ? "green" : "neutral"}
        />
      </div>

      <SectionCard title="Client information">
        <dl className="grid gap-x-8 gap-y-4 px-5 py-4 sm:grid-cols-2">
          <InfoRow label="Client" value={client.name} />
          <InfoRow label="Company" value={companyName} />
          <InfoRow label="Email" value={email || null} />
          <InfoRow label="Status" value={operationalStatus} />
          <InfoRow label="SnelStart" value={snelstartStatusLabel(snelstartStatus)} />
          <InfoRow label="Last document upload" value={client.lastUpload || null} />
          <InfoRow
            label="Last activity"
            value={lastActivity ? `${lastActivity.text} · ${relativeTime(lastActivity.at)}` : null}
          />
          <InfoRow
            label="Portal account created"
            value={portal?.createdAt ? formatDate(portal.createdAt) : null}
          />
        </dl>
      </SectionCard>

      <SectionCard
        title="Documents"
        description="Uploads belonging to this client"
        action={
          <Button size="sm" variant="outline" asChild>
            <Link to="/inbox" search={{ client: id }}>
              View inbox
            </Link>
          </Button>
        }
      >
        {documents.length === 0 ? (
          <EmptyState
            icon={FileStack}
            title="No documents yet"
            description="This client has not uploaded any documents."
          />
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full min-w-[760px] text-[13.5px]">
              <thead className="border-b border-border bg-muted/50 text-[11.5px] tracking-wide text-muted-foreground uppercase">
                <tr>
                  <th className="px-5 py-3 text-left font-semibold">Document</th>
                  <th className="px-3 py-3 text-left font-semibold">Supplier</th>
                  <th className="px-3 py-3 text-left font-semibold">Invoice</th>
                  <th className="px-3 py-3 text-right font-semibold">Amount</th>
                  <th className="px-3 py-3 text-left font-semibold">Uploaded</th>
                  <th className="px-3 py-3 text-left font-semibold">OCR</th>
                  <th className="px-3 py-3 text-left font-semibold">Status</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-border">
                {documents.map((doc) => (
                  <tr key={doc.id} className="transition-colors hover:bg-muted/40">
                    <td className="px-5 py-3">
                      <Link
                        to="/invoices/$id"
                        params={{ id: doc.id }}
                        className="font-medium hover:text-primary"
                      >
                        {doc.file || doc.supplier || doc.id}
                      </Link>
                    </td>
                    <td className="px-3 py-3 text-muted-foreground">{doc.supplier || "—"}</td>
                    <td className="px-3 py-3 text-muted-foreground">{doc.number || "—"}</td>
                    <td className="num px-3 py-3 text-right">
                      {doc.total ? eur(doc.total) : "—"}
                    </td>
                    <td className="px-3 py-3 text-muted-foreground">{doc.uploadedAt || "—"}</td>
                    <td className="px-3 py-3">
                      {doc.confidence > 0 ? (
                        <ConfidenceIndicator value={doc.confidence} compact />
                      ) : (
                        <span className="text-muted-foreground">—</span>
                      )}
                    </td>
                    <td className="px-3 py-3">
                      <div className="flex flex-wrap items-center gap-1.5">
                        <StatusBadge status={doc.status as InvoiceStatus} />
                        <DuplicateBadge status={doc.duplicateStatus} />
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </SectionCard>

      <SectionCard
        title="Queries"
        description="Questions belonging to this client"
        action={
          <Button size="sm" variant="outline" asChild>
            <Link to="/queries">View all queries</Link>
          </Button>
        }
      >
        {queries.length === 0 ? (
          <EmptyState
            icon={MessageSquareText}
            title="No queries yet"
            description="Questions you ask this client will appear here."
          />
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full min-w-[720px] text-[13.5px]">
              <thead className="border-b border-border bg-muted/50 text-[11.5px] tracking-wide text-muted-foreground uppercase">
                <tr>
                  <th className="px-5 py-3 text-left font-semibold">Question</th>
                  <th className="px-3 py-3 text-left font-semibold">Document</th>
                  <th className="px-3 py-3 text-left font-semibold">Priority</th>
                  <th className="px-3 py-3 text-left font-semibold">Status</th>
                  <th className="px-3 py-3 text-left font-semibold">Last activity</th>
                  <th className="px-3 py-3 text-left font-semibold">Created</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-border">
                {queries.map((q) => (
                  <tr key={q.id} className="transition-colors hover:bg-muted/40">
                    <td className="px-5 py-3">
                      <Link
                        to="/queries/$id"
                        params={{ id: q.id }}
                        className="line-clamp-2 font-medium hover:text-primary"
                      >
                        {q.question || q.title || q.id}
                      </Link>
                    </td>
                    <td className="px-3 py-3 text-muted-foreground">
                      {q.invoiceId ? (
                        <Link to="/invoices/$id" params={{ id: q.invoiceId }} className="hover:text-primary">
                          {q.invoiceLabel || q.invoiceId}
                        </Link>
                      ) : (
                        "—"
                      )}
                    </td>
                    <td className="px-3 py-3">
                      <QueryPriorityBadge priority={q.priority} />
                    </td>
                    <td className="px-3 py-3">
                      <Pill tone={queryStatusTone(q.status)}>{q.status}</Pill>
                    </td>
                    <td className="px-3 py-3 text-muted-foreground">{q.lastActivityAt || "—"}</td>
                    <td className="px-3 py-3 text-muted-foreground">{q.createdAt || "—"}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </SectionCard>

      <SectionCard
        title="Bank matching"
        description="Transactions belonging to this client"
        action={
          <Button size="sm" variant="outline" asChild>
            <Link to="/bank" search={{ client: id }}>
              <Landmark size={14} /> Open bank matching
            </Link>
          </Button>
        }
      >
        {!bank || bank.total === 0 ? (
          <EmptyState
            icon={Landmark}
            title="No bank transactions"
            description="Bank transactions for this client will appear here once they are imported."
          />
        ) : (
          <div className="grid gap-3 p-5 sm:grid-cols-2 xl:grid-cols-4">
            <KpiCard label="Unmatched" value={bank.unmatched} icon={Landmark} />
            <KpiCard
              label="Suggested"
              value={bank.suggested}
              icon={Landmark}
              tone={bank.suggested > 0 ? "amber" : "neutral"}
            />
            <KpiCard
              label="Needs review"
              value={bank.needsReview}
              icon={Landmark}
              tone={bank.needsReview > 0 ? "amber" : "neutral"}
            />
            <KpiCard
              label="Matched"
              value={bank.matched}
              icon={Landmark}
              tone={bank.matched > 0 ? "green" : "neutral"}
            />
          </div>
        )}
      </SectionCard>

      <SectionCard title="Activity" description="Recent events for this client">
        {activity.length === 0 ? (
          <EmptyState
            icon={Building2}
            title="No activity yet"
            description="Events will appear here as work progresses."
          />
        ) : (
          <ActivityTimeline events={activity} showLinks />
        )}
      </SectionCard>
    </div>
  );
}

function InfoRow({ label, value }: { label: string; value?: string | null }) {
  return (
    <div>
      <dt className="text-[11.5px] font-semibold tracking-wide text-muted-foreground uppercase">{label}</dt>
      <dd className="mt-1 text-[13.5px] text-foreground">{value || "—"}</dd>
    </div>
  );
}

function formatDate(iso: string): string {
  const ts = Date.parse(iso);
  if (Number.isNaN(ts)) return iso;
  return new Date(ts).toLocaleDateString("en-GB", {
    day: "numeric",
    month: "short",
    year: "numeric",
  });
}
