import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { useMemo, useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useServerFn } from "@tanstack/react-start";
import { toast } from "sonner";
import { Loader2, RefreshCw, Trash2 } from "lucide-react";
import { supabase } from "@/integrations/supabase/client";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { listLeads, updateLead, deleteLead, isAdmin, type LeadRow } from "@/lib/admin.functions";

export const Route = createFileRoute("/_authenticated/admin")({
  head: () => ({
    meta: [
      { title: "Lead Dashboard — Gatavase Corporation" },
      { name: "description", content: "Manage contact form submissions for Gatavase Corporation." },
      { name: "robots", content: "noindex" },
      { property: "og:title", content: "Lead Dashboard — Gatavase Corporation" },
      { property: "og:description", content: "Internal lead management dashboard." },
      { property: "og:url", content: "/admin" },
    ],
    links: [{ rel: "canonical", href: "/admin" }],
  }),
  component: AdminPage,
});

const STATUSES = ["new", "contacted", "qualified", "archived"] as const;

function AdminPage() {
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const fetchLeads = useServerFn(listLeads);
  const checkAdmin = useServerFn(isAdmin);
  const patchLead = useServerFn(updateLead);
  const removeLead = useServerFn(deleteLead);

  const [filter, setFilter] = useState<"all" | (typeof STATUSES)[number]>("all");
  const [search, setSearch] = useState("");

  const adminQuery = useQuery({ queryKey: ["is-admin"], queryFn: () => checkAdmin({}) });
  const leadsQuery = useQuery({
    queryKey: ["leads"],
    queryFn: () => fetchLeads({}),
    enabled: adminQuery.data?.isAdmin === true,
  });

  const updateMutation = useMutation({
    mutationFn: (input: { id: string; status?: string; internal_notes?: string }) =>
      patchLead({ data: input }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["leads"] });
      toast.success("Lead updated");
    },
    onError: (e) => toast.error(e instanceof Error ? e.message : "Update failed"),
  });

  const deleteMutation = useMutation({
    mutationFn: (id: string) => removeLead({ data: { id } }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["leads"] });
      toast.success("Lead deleted");
    },
    onError: (e) => toast.error(e instanceof Error ? e.message : "Delete failed"),
  });

  const leads = useMemo(() => {
    const rows = leadsQuery.data ?? [];
    const q = search.trim().toLowerCase();
    return rows.filter((row) => {
      if (filter !== "all" && row.status !== filter) return false;
      if (!q) return true;
      return [row.name, row.email, row.company ?? "", row.message]
        .join(" ")
        .toLowerCase()
        .includes(q);
    });
  }, [leadsQuery.data, filter, search]);

  async function signOut() {
    await queryClient.cancelQueries();
    queryClient.clear();
    await supabase.auth.signOut();
    navigate({ to: "/auth", replace: true });
  }

  if (adminQuery.isLoading) {
    return (
      <div className="grid min-h-[60vh] place-items-center">
        <Loader2 className="size-6 animate-spin text-primary" />
      </div>
    );
  }

  if (!adminQuery.data?.isAdmin) {
    return (
      <div className="mx-auto max-w-lg px-5 py-28 text-center">
        <h1 className="text-2xl font-bold">Admin access required</h1>
        <p className="mt-3 text-sm text-muted-foreground">
          You are signed in as {adminQuery.data?.email ?? "an unknown account"}, but this account
          does not have the admin role yet. Ask an administrator to grant it.
        </p>
        <div className="mt-6 flex justify-center gap-2">
          <Button variant="outline" onClick={signOut}>
            Sign out
          </Button>
          <Button asChild>
            <Link to="/">Go home</Link>
          </Button>
        </div>
      </div>
    );
  }

  return (
    <section className="mx-auto max-w-6xl px-5 py-16">
      <div className="flex flex-wrap items-end justify-between gap-4">
        <div>
          <p className="font-mono text-xs tracking-[0.2em] text-primary uppercase">Dashboard</p>
          <h1 className="mt-3 text-3xl font-bold">Contact submissions</h1>
          <p className="mt-2 text-sm text-muted-foreground">
            {leadsQuery.data?.length ?? 0} total leads · signed in as {adminQuery.data.email}
          </p>
        </div>
        <div className="flex gap-2">
          <Button
            variant="outline"
            size="sm"
            onClick={() => queryClient.invalidateQueries({ queryKey: ["leads"] })}
          >
            <RefreshCw className="size-4" /> Refresh
          </Button>
          <Button variant="outline" size="sm" onClick={signOut}>
            Sign out
          </Button>
        </div>
      </div>

      <div className="mt-8 flex flex-wrap items-center gap-2">
        {(["all", ...STATUSES] as const).map((s) => (
          <button
            key={s}
            onClick={() => setFilter(s)}
            className={`rounded-full border px-4 py-1.5 text-xs capitalize transition-colors ${
              filter === s
                ? "border-primary bg-primary/15 text-primary"
                : "border-border text-muted-foreground hover:text-foreground"
            }`}
          >
            {s}
          </button>
        ))}
        <Input
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          placeholder="Search name, email, company or message"
          className="ml-auto max-w-xs"
        />
      </div>

      {leadsQuery.isLoading ? (
        <div className="grid py-20 place-items-center">
          <Loader2 className="size-6 animate-spin text-primary" />
        </div>
      ) : leads.length === 0 ? (
        <p className="panel mt-8 p-10 text-center text-sm text-muted-foreground">
          No submissions match this view yet.
        </p>
      ) : (
        <div className="mt-8 space-y-4">
          {leads.map((lead) => (
            <LeadCard
              key={lead.id}
              lead={lead}
              onUpdate={(patch) => updateMutation.mutate({ id: lead.id, ...patch })}
              onDelete={() => deleteMutation.mutate(lead.id)}
            />
          ))}
        </div>
      )}
    </section>
  );
}

function LeadCard({
  lead,
  onUpdate,
  onDelete,
}: {
  lead: LeadRow;
  onUpdate: (patch: { status?: string; internal_notes?: string }) => void;
  onDelete: () => void;
}) {
  const [notes, setNotes] = useState(lead.internal_notes ?? "");

  return (
    <div className="panel p-6">
      <div className="flex flex-wrap items-start justify-between gap-4">
        <div>
          <p className="font-semibold">{lead.name}</p>
          <p className="text-sm text-muted-foreground">
            <a href={`mailto:${lead.email}`} className="hover:text-foreground">
              {lead.email}
            </a>
            {lead.company ? ` · ${lead.company}` : ""}
          </p>
          <p className="mt-1 font-mono text-xs text-muted-foreground">
            {new Date(lead.created_at).toLocaleString()} · via {lead.source}
          </p>
        </div>
        <div className="flex items-center gap-2">
          <select
            value={lead.status}
            onChange={(e) => onUpdate({ status: e.target.value })}
            className="rounded-md border border-border bg-background px-3 py-1.5 text-xs capitalize"
          >
            {STATUSES.map((s) => (
              <option key={s} value={s}>
                {s}
              </option>
            ))}
          </select>
          <Button variant="outline" size="icon" onClick={onDelete} aria-label="Delete lead">
            <Trash2 className="size-4" />
          </Button>
        </div>
      </div>

      <p className="mt-4 text-sm leading-relaxed whitespace-pre-line text-muted-foreground">
        {lead.message}
      </p>

      <div className="mt-4 flex flex-col gap-2 sm:flex-row">
        <Textarea
          value={notes}
          onChange={(e) => setNotes(e.target.value)}
          rows={2}
          maxLength={4000}
          placeholder="Internal notes"
          className="flex-1"
        />
        <Button
          variant="outline"
          size="sm"
          className="self-start"
          onClick={() => onUpdate({ internal_notes: notes })}
        >
          Save note
        </Button>
      </div>
    </div>
  );
}
