import { useState } from "react";
import { Form, redirect, useSearchParams } from "react-router";
import type { Route } from "./+types/admin.users";

import { auth } from "~/lib/auth.server";
import {
  isUserAdmin,
  findUsersPaginated,
  findUserByUsername,
  updateUser,
  USERNAME_RE,
} from "~/models/user";
import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
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 { Pencil, Check, X } from "lucide-react";

const PAGE_SIZE = 25;

export function meta(): Route.MetaDescriptors {
  return [{ title: "Users — Brackt Admin" }];
}

export async function loader(args: Route.LoaderArgs) {
  const session = await auth.api.getSession({ headers: args.request.headers });
  const userId = session?.user.id ?? null;
  if (!userId) throw redirect("/");

  const isAdmin = await isUserAdmin(userId);
  if (!isAdmin) throw redirect("/");

  const searchParams = new URL(args.request.url).searchParams;
  const page = Math.max(0, parseInt(searchParams.get("page") ?? "0", 10) || 0);
  const search = searchParams.get("search") ?? "";

  const { users, total, hasMore } = await findUsersPaginated({
    limit: PAGE_SIZE,
    offset: page * PAGE_SIZE,
    search: search || undefined,
  });

  const totalPages = Math.ceil(total / PAGE_SIZE);
  return { users, page, totalPages, total, hasMore, search };
}

export async function action(args: Route.ActionArgs) {
  const session = await auth.api.getSession({ headers: args.request.headers });
  const userId = session?.user.id ?? null;
  if (!userId) throw redirect("/");

  const isAdmin = await isUserAdmin(userId);
  if (!isAdmin) throw redirect("/");

  const formData = await args.request.formData();
  const intent = formData.get("intent");

  if (intent === "update-username") {
    const targetUserId = formData.get("userId");
    const username = formData.get("username");

    if (typeof targetUserId !== "string" || typeof username !== "string") {
      return { error: "Invalid request" };
    }

    const trimmed = username.trim();

    if (trimmed !== "" && !USERNAME_RE.test(trimmed)) {
      return {
        error:
          "Username must be 3–30 characters and contain only letters, numbers, underscores, or hyphens.",
        userId: targetUserId,
      };
    }

    if (trimmed !== "") {
      const existing = await findUserByUsername(trimmed);
      if (existing && existing.id !== targetUserId) {
        return { error: "That username is already taken.", userId: targetUserId };
      }
    }

    await updateUser(targetUserId, { username: trimmed || null });
    return { success: true };
  }

  return {};
}

export default function AdminUsers({ loaderData, actionData }: Route.ComponentProps) {
  const { users, page, totalPages, total, search } = loaderData;
  const [searchParams] = useSearchParams();
  const [editingId, setEditingId] = useState<string | null>(null);
  const [editValue, setEditValue] = useState("");

  function startEdit(userId: string, currentUsername: string | null) {
    setEditingId(userId);
    setEditValue(currentUsername ?? "");
  }

  function cancelEdit() {
    setEditingId(null);
    setEditValue("");
  }

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

  return (
    <div className="p-8">
      <div className="mb-6 flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold">Users</h1>
          <p className="text-muted-foreground text-sm mt-1">{total} total users</p>
        </div>
      </div>

      <Card>
        <CardHeader>
          <CardTitle>All Users</CardTitle>
          <CardDescription>Search and manage user accounts.</CardDescription>
          <Form method="get" className="mt-2 flex gap-2">
            <Input
              name="search"
              placeholder="Search by email, username, or display name…"
              defaultValue={search}
              className="max-w-sm"
            />
            <input type="hidden" name="page" value="0" />
            <Button type="submit" variant="secondary">
              Search
            </Button>
            {search && (
              <Button variant="ghost" asChild>
                <a href="?page=0">Clear</a>
              </Button>
            )}
          </Form>
        </CardHeader>
        <CardContent>
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Email</TableHead>
                <TableHead>Username</TableHead>
                <TableHead>Display Name</TableHead>
                <TableHead>Admin</TableHead>
                <TableHead>Joined</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {users.length === 0 && (
                <TableRow>
                  <TableCell colSpan={5} className="text-center text-muted-foreground py-8">
                    No users found.
                  </TableCell>
                </TableRow>
              )}
              {users.map((user) => {
                const isEditing = editingId === user.id;
                const hasError = actionData && "error" in actionData && actionData.userId === user.id;
                return (
                  <TableRow key={user.id}>
                    <TableCell className="font-mono text-sm">{user.email}</TableCell>
                    <TableCell>
                      {isEditing ? (
                        <div className="flex flex-col gap-1">
                          <Form method="post" className="flex items-center gap-1">
                            <input type="hidden" name="intent" value="update-username" />
                            <input type="hidden" name="userId" value={user.id} />
                            <Input
                              name="username"
                              value={editValue}
                              onChange={(e) => setEditValue(e.target.value)}
                              className="h-7 w-40 text-sm"
                              autoFocus
                              placeholder="leave blank to clear"
                            />
                            <Button
                              type="submit"
                              size="icon"
                              variant="ghost"
                              className="h-7 w-7"
                              title="Save"
                              onClick={() => setEditingId(null)}
                            >
                              <Check className="h-4 w-4" />
                            </Button>
                            <Button
                              type="button"
                              size="icon"
                              variant="ghost"
                              className="h-7 w-7"
                              title="Cancel"
                              onClick={cancelEdit}
                            >
                              <X className="h-4 w-4" />
                            </Button>
                          </Form>
                          {hasError && (
                            <p className="text-destructive text-xs">{actionData.error}</p>
                          )}
                        </div>
                      ) : (
                        <div className="flex items-center gap-1">
                          <span className="text-sm">{user.username ?? "—"}</span>
                          <Button
                            type="button"
                            size="icon"
                            variant="ghost"
                            className="h-6 w-6 opacity-50 hover:opacity-100"
                            title="Edit username"
                            onClick={() => startEdit(user.id, user.username)}
                          >
                            <Pencil className="h-3 w-3" />
                          </Button>
                        </div>
                      )}
                    </TableCell>
                    <TableCell className="text-sm text-muted-foreground">
                      {user.displayName ?? "—"}
                    </TableCell>
                    <TableCell>
                      {user.isAdmin && <Badge variant="secondary">Admin</Badge>}
                    </TableCell>
                    <TableCell className="text-sm text-muted-foreground">
                      {new Date(user.createdAt).toLocaleDateString()}
                    </TableCell>
                  </TableRow>
                );
              })}
            </TableBody>
          </Table>

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