"use client";

import * as React from "react";

import {
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  useReactTable,
  type ColumnDef,
  type PaginationState,
} from "@tanstack/react-table";
import { Download } from "lucide-react";

import {
  DataTablePagination,
  DataTableShell,
  downloadCsv,
  matchesText,
} from "@/app/dashboard/_components/data-table";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";

import { PrincipalBadge } from "./principal-badge";
import type { AuditEntry } from "./types";
import { formatDisplayDateTime } from "@/lib/format/dates";

function exportAudit(rows: AuditEntry[]) {
  downloadCsv({
    filename: "rbac-audit-log",
    headers: ["Timestamp", "Actor", "Target", "Action", "Item", "Detail"],
    rows,
    toRow: (row) => [
      row.timestamp,
      row.actorDisplayName,
      row.targetDisplayName,
      row.action,
      row.itemName,
      row.detail,
    ],
  });
}

export function AuditLogTable({ data }: { data: AuditEntry[] }) {
  const [actorQuery, setActorQuery] = React.useState("");
  const [targetQuery, setTargetQuery] = React.useState("");
  const [pagination, setPagination] = React.useState<PaginationState>({
    pageIndex: 0,
    pageSize: 20,
  });

  const filtered = React.useMemo(() => {
    return data.filter((row) => {
      if (actorQuery && !matchesText(row.actorDisplayName, actorQuery) && !matchesText(row.actorPrincipal, actorQuery)) {
        return false;
      }
      if (targetQuery && !matchesText(row.targetDisplayName, targetQuery) && !matchesText(row.targetPrincipal, targetQuery)) {
        return false;
      }
      return true;
    });
  }, [data, actorQuery, targetQuery]);

  const columns = React.useMemo<ColumnDef<AuditEntry>[]>(
    () => [
      {
        accessorKey: "timestamp",
        header: "When",
        cell: ({ row }) => (
          <span className="text-muted-foreground text-sm">
            {formatDisplayDateTime(row.original.timestamp)}
          </span>
        ),
      },
      {
        id: "actor",
        header: "Actor",
        cell: ({ row }) => (
          <div className="space-y-1">
            <div className="text-sm">{row.original.actorDisplayName}</div>
            <PrincipalBadge principal={row.original.actorPrincipal} />
          </div>
        ),
      },
      {
        id: "target",
        header: "Target",
        cell: ({ row }) => (
          <div className="space-y-1">
            <div className="text-sm">{row.original.targetDisplayName}</div>
            <PrincipalBadge principal={row.original.targetPrincipal} />
          </div>
        ),
      },
      {
        accessorKey: "action",
        header: "Action",
        cell: ({ row }) => (
          <span className="rounded bg-muted px-2 py-0.5 font-mono text-xs uppercase">
            {row.original.action}
          </span>
        ),
      },
      {
        id: "domain",
        header: "Domain",
        cell: ({ row }) =>
          row.original.domain ? (
            <span className="font-mono text-xs">{row.original.domain}</span>
          ) : (
            <span className="text-muted-foreground text-xs">—</span>
          ),
      },
      {
        id: "principalType",
        header: "Scope",
        cell: ({ row }) =>
          row.original.principalType ? (
            <span className="font-mono text-xs capitalize">{row.original.principalType}</span>
          ) : (
            <span className="text-muted-foreground text-xs">—</span>
          ),
      },
      {
        accessorKey: "itemName",
        header: "Item",
        cell: ({ row }) => <span className="font-mono text-sm">{row.original.itemName}</span>,
      },
      {
        accessorKey: "detail",
        header: "Detail",
        cell: ({ row }) => (
          <span className="text-muted-foreground text-sm">{row.original.detail}</span>
        ),
      },
    ],
    [],
  );

  const table = useReactTable({
    data: filtered,
    columns,
    state: { pagination },
    onPaginationChange: setPagination,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getRowId: (row) => row.id,
  });

  return (
    <div className="space-y-4">
      <div className="flex flex-wrap items-end justify-between gap-3">
        <div className="flex flex-wrap items-end gap-3">
          <div className="space-y-1">
            <Label htmlFor="audit-actor" className="text-xs">
              Actor
            </Label>
            <Input
              id="audit-actor"
              value={actorQuery}
              onChange={(e) => setActorQuery(e.target.value)}
              placeholder="Filter actor…"
              className="h-9 w-[180px]"
            />
          </div>
          <div className="space-y-1">
            <Label htmlFor="audit-target" className="text-xs">
              Target
            </Label>
            <Input
              id="audit-target"
              value={targetQuery}
              onChange={(e) => setTargetQuery(e.target.value)}
              placeholder="Filter target…"
              className="h-9 w-[180px]"
            />
          </div>
        </div>
        <Button type="button" variant="outline" size="sm" onClick={() => exportAudit(filtered)}>
          <Download className="size-4" />
          Export CSV
        </Button>
      </div>
      <DataTableShell
        table={table}
        columnCount={columns.length}
        emptyMessage="No audit entries found."
      />
      <DataTablePagination
        table={table}
        totalRows={filtered.length}
        itemNoun="entry"
        idPrefix="audit"
      />
    </div>
  );
}
