import { auth } from "~/lib/auth.server";
import { format } from "date-fns";
import { Link, Form, useSearchParams } from "react-router";
import type { Route } from "./+types/$leagueId.audit-log";
import { Button } from "~/components/ui/button";
import { Badge } from "~/components/ui/badge";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "~/components/ui/card";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "~/components/ui/table";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "~/components/ui/select";
import { findLeagueById, isCommissioner, isUserLeagueMember } from "~/models";
import { findCurrentSeasonWithSports } from "~/models/season";
import { findTeamsBySeasonId } from "~/models/team";
import { getAuditLogForSeason, type AuditAction, type AuditLogEntry } from "~/models/audit-log";
import { AUDIT_ACTION_LABELS, formatAuditDetail } from "~/lib/audit-log-display";
import * as schema from "~/database/schema";

const VALID_AUDIT_ACTIONS = new Set<string>(schema.auditActionEnum.enumValues);

export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
  return [{ title: `Audit Log — ${data?.league?.name ?? "League"} - Brackt` }];
}

const PAGE_SIZE = 50;

export async function loader(args: Route.LoaderArgs) {
  const session = await auth.api.getSession({ headers: args.request.headers });
  const userId = session?.user.id ?? null;
  const { params, request } = args;
  const { leagueId } = params;

  if (!userId) {
    throw new Response("You must be logged in to view this page", {
      status: 401,
    });
  }

  const league = await findLeagueById(leagueId);
  if (!league) {
    throw new Response("League not found", { status: 404 });
  }

  const [userIsCommissioner, userIsMember] = await Promise.all([
    isCommissioner(leagueId, userId),
    isUserLeagueMember(leagueId, userId),
  ]);

  if (!userIsCommissioner && !userIsMember) {
    throw new Response("You do not have access to this league", {
      status: 403,
    });
  }

  const season = await findCurrentSeasonWithSports(leagueId);

  if (!season) {
    return {
      league,
      season: null,
      auditLog: { entries: [] as AuditLogEntry[], total: 0, hasMore: false },
      teams: [] as Array<{ id: string; name: string }>,
      page: 0,
      isUserCommissioner: userIsCommissioner,
    };
  }

  const searchParams = new URL(request.url).searchParams;
  const page = Math.max(0, parseInt(searchParams.get("page") ?? "0", 10) || 0);
  const rawAction = searchParams.get("action");
  const actionFilter: AuditAction | null =
    rawAction && VALID_AUDIT_ACTIONS.has(rawAction) ? (rawAction as AuditAction) : null;

  const [auditLog, teams] = await Promise.all([
    getAuditLogForSeason(season.id, {
      limit: PAGE_SIZE,
      offset: page * PAGE_SIZE,
      actions: actionFilter ? [actionFilter] : undefined,
    }),
    findTeamsBySeasonId(season.id),
  ]);

  return {
    league,
    season,
    auditLog,
    teams: teams.map((t) => ({ id: t.id, name: t.name })),
    page,
    isUserCommissioner: userIsCommissioner,
  };
}

function getActionBadgeVariant(
  action: string
): "default" | "secondary" | "destructive" | "outline" {
  if (action === "draft_reset" || action === "draft_rollback") {
    return "destructive";
  }
  if (
    action === "draft_started" ||
    action === "draft_paused" ||
    action === "draft_resumed"
  ) {
    return "secondary";
  }
  if (
    action === "league_settings_changed" ||
    action === "draft_settings_changed" ||
    action === "scoring_rules_changed" ||
    action === "sports_changed"
  ) {
    return "outline";
  }
  return "default";
}

interface AuditLogRowProps {
  entry: AuditLogEntry;
  teamMap: Map<string, string>;
}

function AuditLogRow({ entry, teamMap }: AuditLogRowProps) {
  const affectedTeamNames =
    entry.affectedTeamIds && entry.affectedTeamIds.length > 0
      ? entry.affectedTeamIds
          .map((id) => teamMap.get(id) ?? id)
          .join(", ")
      : "—";

  return (
    <TableRow>
      <TableCell className="whitespace-nowrap text-sm text-muted-foreground">
        {format(new Date(entry.createdAt), "MMM d, yyyy HH:mm")}
      </TableCell>
      <TableCell className="text-sm font-medium">
        {entry.actorDisplayName ?? entry.actorUserId}
      </TableCell>
      <TableCell>
        <Badge variant={getActionBadgeVariant(entry.action)}>
          {AUDIT_ACTION_LABELS[entry.action] ?? entry.action}
        </Badge>
      </TableCell>
      <TableCell className="text-sm text-muted-foreground">
        {affectedTeamNames}
      </TableCell>
      <TableCell className="text-sm text-muted-foreground max-w-xs">
        {formatAuditDetail(entry)}
      </TableCell>
    </TableRow>
  );
}

export default function AuditLogPage({ loaderData }: Route.ComponentProps) {
  const { league, season, auditLog, teams, page, isUserCommissioner } =
    loaderData;
  const [searchParams] = useSearchParams();
  const actionFilter = searchParams.get("action") ?? "";

  const teamMap = new Map(teams.map((t) => [t.id, t.name]));
  const totalPages = Math.ceil(auditLog.total / PAGE_SIZE);

  function buildPageUrl(newPage: number) {
    const p = new URLSearchParams(searchParams);
    p.set("page", String(newPage));
    return `?${p.toString()}`;
  }

  return (
    <div className="container max-w-5xl mx-auto py-8 px-4">
      {/* Header */}
      <div className="flex items-center justify-between mb-6">
        <div>
          <h1 className="text-2xl font-bold">Audit Log</h1>
          <p className="text-muted-foreground">{league.name}</p>
        </div>
        <div className="flex gap-2">
          {isUserCommissioner && (
            <Button variant="outline" asChild>
              <Link to={`/leagues/${league.id}/settings`}>Settings</Link>
            </Button>
          )}
          <Button variant="outline" asChild>
            <Link to={`/leagues/${league.id}`}>Back to League</Link>
          </Button>
        </div>
      </div>

      {!season ? (
        <Card>
          <CardContent className="py-8 text-center text-muted-foreground">
            No season found for this league.
          </CardContent>
        </Card>
      ) : (
        <>
          {/* Filter bar */}
          <Card className="mb-4">
            <CardContent className="py-4">
              <Form method="get" className="flex gap-3 items-center">
                <Select name="action" defaultValue={actionFilter || ""}>
                  <SelectTrigger className="w-[220px]">
                    <SelectValue placeholder="All actions" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="">All actions</SelectItem>
                    {Object.entries(AUDIT_ACTION_LABELS).map(
                      ([value, label]) => (
                        <SelectItem key={value} value={value}>
                          {label}
                        </SelectItem>
                      )
                    )}
                  </SelectContent>
                </Select>
                <Button type="submit" size="sm">
                  Filter
                </Button>
                {actionFilter && (
                  <Button variant="outline" size="sm" asChild>
                    <Link to={`/leagues/${league.id}/audit-log`}>
                      Clear filter
                    </Link>
                  </Button>
                )}
              </Form>
            </CardContent>
          </Card>

          {/* Results table */}
          <Card>
            <CardHeader>
              <CardTitle>Commissioner Actions</CardTitle>
              <CardDescription>
                {auditLog.total === 0
                  ? "No entries found"
                  : `${auditLog.total} ${auditLog.total === 1 ? "entry" : "entries"}`}
                {totalPages > 1 &&
                  ` — page ${page + 1} of ${totalPages}`}
              </CardDescription>
            </CardHeader>
            <CardContent>
              {auditLog.entries.length === 0 ? (
                <p className="text-center text-muted-foreground py-8">
                  No activity recorded yet.
                </p>
              ) : (
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead>Time</TableHead>
                      <TableHead>Commissioner</TableHead>
                      <TableHead>Action</TableHead>
                      <TableHead>Teams Affected</TableHead>
                      <TableHead>Details</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {auditLog.entries.map((entry) => (
                      <AuditLogRow
                        key={entry.id}
                        entry={entry}
                        teamMap={teamMap}
                      />
                    ))}
                  </TableBody>
                </Table>
              )}

              {/* Pagination */}
              {totalPages > 1 && (
                <div className="flex gap-2 mt-4 justify-center">
                  {page > 0 && (
                    <Button variant="outline" size="sm" asChild>
                      <Link to={buildPageUrl(page - 1)}>Previous</Link>
                    </Button>
                  )}
                  <span className="flex items-center text-sm text-muted-foreground px-2">
                    Page {page + 1} of {totalPages}
                  </span>
                  {auditLog.hasMore && (
                    <Button variant="outline" size="sm" asChild>
                      <Link to={buildPageUrl(page + 1)}>Next</Link>
                    </Button>
                  )}
                </div>
              )}
            </CardContent>
          </Card>
        </>
      )}
    </div>
  );
}
