import { useState } from "react";
import { createFileRoute } from "@tanstack/react-router";
import { keepPreviousData, useQuery } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { VoterTable } from "@/components/audience/voter-table";
import {
  DEFAULT_FILTERS,
  FilterPanel,
  type AudienceFilters,
} from "@/components/audience/filter-panel";
import { audienceCountFn, listSegmentsFn, listVotersFn } from "@/lib/voters/voters.functions";
import {
  Bookmark,
  CheckCheck,
  ChevronDown,
  Download,
  Megaphone,
  MoreHorizontal,
  Search,
  Sparkles,
  Tag,
  Trash2,
  X,
} from "lucide-react";
import { formatDistanceToNow } from "date-fns";

export const Route = createFileRoute("/audiences/")({
  component: AudiencesDatabase,
});

function compactNumber(n: number) {
  if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(2)}M`;
  if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;
  return n.toString();
}

const PAGE_SIZE = 100;

function AudiencesDatabase() {
  const [filters, setFilters] = useState<AudienceFilters>(DEFAULT_FILTERS);
  const [selected, setSelected] = useState<Set<string>>(new Set());

  // Voter listing — server paginated. We always fetch the first page
  // and rely on virtualization for the visible window. Heavier scroll
  // -> infinite query can be a follow-up.
  const votersQuery = useQuery({
    queryKey: ["voters", "list", filters],
    queryFn: () =>
      listVotersFn({ data: { filters, page: 1, pageSize: PAGE_SIZE, sort: "added_desc" } }),
    placeholderData: keepPreviousData,
  });

  const countQuery = useQuery({
    queryKey: ["voters", "count", filters],
    queryFn: () => audienceCountFn({ data: { filters } }),
    placeholderData: keepPreviousData,
  });

  const segmentsQuery = useQuery({
    queryKey: ["voters", "segments"],
    queryFn: () => listSegmentsFn(),
  });

  const voters = votersQuery.data?.rows ?? [];
  const totalCount = countQuery.data?.total ?? votersQuery.data?.total ?? 0;
  const matchedCount = votersQuery.data?.total ?? 0;
  const segments = segmentsQuery.data ?? [];

  const toggle = (id: string) =>
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) {
        next.delete(id);
      } else {
        next.add(id);
      }
      return next;
    });

  const toggleAll = () =>
    setSelected((prev) => {
      const allOnPage = voters.every((v) => prev.has(v.id));
      if (allOnPage) {
        const next = new Set(prev);
        voters.forEach((v) => next.delete(v.id));
        return next;
      }
      const next = new Set(prev);
      voters.forEach((v) => next.add(v.id));
      return next;
    });

  const hasSelection = selected.size > 0;

  return (
    <div className="grid lg:grid-cols-[280px_1fr] gap-4">
      {/* Sidebar: saved segments + filters */}
      <div className="space-y-4">
        <Card>
          <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
            <CardTitle className="text-sm flex items-center gap-2">
              <Bookmark className="h-4 w-4 text-primary" /> Saved segments
            </CardTitle>
            <Button variant="ghost" size="sm" className="h-6 px-2 text-[11px]">
              Manage
            </Button>
          </CardHeader>
          <CardContent className="space-y-1.5">
            {segments.length === 0 && (
              <p className="text-[11px] text-muted-foreground px-2 py-1.5">
                No saved segments yet. Create one in the segment builder.
              </p>
            )}
            {segments.map((s) => (
              <button
                key={s.id}
                type="button"
                onClick={() => setFilters({ ...s.filters })}
                className="w-full text-left rounded-md px-2 py-2 text-xs hover:bg-muted/60 transition-colors"
              >
                <div className="flex items-center justify-between gap-2">
                  <span className="font-medium truncate">{s.name}</span>
                  <span className="text-[10px] text-muted-foreground shrink-0 tabular-nums">
                    {s.cachedCount != null ? compactNumber(s.cachedCount) : "—"}
                  </span>
                </div>
                <div className="mt-0.5 flex items-center gap-1.5 text-[10px] text-muted-foreground">
                  <span>{s.channels.length ? s.channels.join(" · ") : "No channels"}</span>
                  <span>·</span>
                  <span>{formatDistanceToNow(new Date(s.updatedAt), { addSuffix: true })}</span>
                </div>
              </button>
            ))}
          </CardContent>
        </Card>

        <FilterPanel filters={filters} onChange={setFilters} />
      </div>

      {/* Main: table */}
      <div className="space-y-3 min-w-0">
        {/* Toolbar */}
        <div className="flex flex-col sm:flex-row sm:items-center gap-2 justify-between">
          <div className="relative flex-1 max-w-md">
            <Search className="absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" />
            <Input
              value={filters.search}
              onChange={(e) => setFilters({ ...filters, search: e.target.value })}
              placeholder="Search name, phone or voter ID…"
              className="h-9 pl-8 text-sm"
            />
          </div>

          <div className="flex items-center gap-2 text-xs text-muted-foreground">
            <span className="tabular-nums">
              <span className="font-medium text-foreground">{matchedCount.toLocaleString()}</span>{" "}
              of {totalCount.toLocaleString()}
            </span>
            <Button variant="outline" size="sm" className="gap-1.5">
              <Download className="h-3.5 w-3.5" /> Export
            </Button>
            <DropdownMenu>
              <DropdownMenuTrigger asChild>
                <Button variant="outline" size="sm" className="gap-1">
                  More <ChevronDown className="h-3 w-3" />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent align="end">
                <DropdownMenuItem>
                  <Sparkles className="h-3.5 w-3.5 mr-2" /> AI suggest segments
                </DropdownMenuItem>
                <DropdownMenuItem>
                  <Tag className="h-3.5 w-3.5 mr-2" /> Add tag to selection
                </DropdownMenuItem>
                <DropdownMenuSeparator />
                <DropdownMenuItem className="text-destructive">
                  <Trash2 className="h-3.5 w-3.5 mr-2" /> Remove selected
                </DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
          </div>
        </div>

        {/* Bulk actions bar */}
        {hasSelection && (
          <div className="flex items-center justify-between rounded-lg border border-primary/30 bg-primary/[0.04] px-3 py-2 text-xs">
            <div className="flex items-center gap-2">
              <CheckCheck className="h-4 w-4 text-primary" />
              <span>
                <span className="font-medium">{selected.size.toLocaleString()}</span> selected
              </span>
            </div>
            <div className="flex items-center gap-1">
              <Button size="sm" variant="ghost" className="h-7 px-2 text-[11px]">
                <Bookmark className="h-3 w-3 mr-1" /> Save as segment
              </Button>
              <Button size="sm" variant="ghost" className="h-7 px-2 text-[11px]">
                <Megaphone className="h-3 w-3 mr-1" /> Launch campaign
              </Button>
              <Button size="sm" variant="ghost" className="h-7 px-2 text-[11px]">
                <Tag className="h-3 w-3 mr-1" /> Tag
              </Button>
              <Button
                size="sm"
                variant="ghost"
                className="h-7 px-2 text-[11px] text-destructive hover:text-destructive"
              >
                <Trash2 className="h-3 w-3 mr-1" /> Remove
              </Button>
              <Button
                size="sm"
                variant="ghost"
                className="h-7 w-7 p-0"
                onClick={() => setSelected(new Set())}
              >
                <X className="h-3.5 w-3.5" />
              </Button>
            </div>
          </div>
        )}

        {/* Active filter pills */}
        <FilterPills
          filters={filters}
          onClear={(key, val) => {
            if (key === "consentOnly") return setFilters({ ...filters, consentOnly: false });
            if (key === "search") return setFilters({ ...filters, search: "" });
            if (key === "ageRange") return setFilters({ ...filters, ageRange: [18, 70] });
            const arr = filters[key] as string[];
            setFilters({ ...filters, [key]: arr.filter((v) => v !== val) });
          }}
        />

        <VoterTable voters={voters} selected={selected} onToggle={toggle} onToggleAll={toggleAll} />

        <div className="flex items-center justify-between text-[11px] text-muted-foreground px-1">
          <span>
            {votersQuery.isFetching ? "Loading…" : "Virtualized list"} · showing{" "}
            {voters.length.toLocaleString()} of {matchedCount.toLocaleString()} matched rows
          </span>
          <div className="flex items-center gap-2">
            <Badge variant="outline" className="text-[10px]">
              {totalCount.toLocaleString()} supporters in database
            </Badge>
            <Button variant="ghost" size="sm" className="h-6 px-2 text-[11px]">
              <MoreHorizontal className="h-3 w-3" />
            </Button>
          </div>
        </div>
      </div>
    </div>
  );
}

function FilterPills({
  filters,
  onClear,
}: {
  filters: AudienceFilters;
  onClear: (key: keyof AudienceFilters, value?: string) => void;
}) {
  const pills: { key: keyof AudienceFilters; value?: string; label: string }[] = [];
  filters.states.forEach((s) => pills.push({ key: "states", value: s, label: `State: ${s}` }));
  filters.lgas.forEach((s) => pills.push({ key: "lgas", value: s, label: `LGA: ${s}` }));
  filters.wards.forEach((s) => pills.push({ key: "wards", value: s, label: `Ward: ${s}` }));
  filters.genders.forEach((s) => pills.push({ key: "genders", value: s, label: s }));
  filters.languages.forEach((s) => pills.push({ key: "languages", value: s, label: s }));
  if (filters.ageRange[0] !== 18 || filters.ageRange[1] !== 70)
    pills.push({ key: "ageRange", label: `Age ${filters.ageRange[0]}–${filters.ageRange[1]}` });
  if (!filters.consentOnly) pills.push({ key: "consentOnly", label: "Including non-opted-in" });

  if (pills.length === 0) return null;
  return (
    <div className="flex flex-wrap gap-1.5">
      {pills.map((p, i) => (
        <button
          key={i}
          type="button"
          onClick={() => onClear(p.key, p.value)}
          className="inline-flex items-center gap-1 rounded-full border border-border bg-muted/40 px-2 py-0.5 text-[11px] hover:bg-muted"
        >
          {p.label}
          <X className="h-3 w-3 text-muted-foreground" />
        </button>
      ))}
    </div>
  );
}
