import { redirect, Form } from "react-router";
import { auth } from "~/lib/auth.server";
import { findUserById, findUserByUsername, updateUser, USERNAME_RE } from "~/models/user";
import type { Route } from "./+types/onboarding";
import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "~/components/ui/card";

export function meta(): Route.MetaDescriptors {
  return [{ title: "Choose a Username - Brackt" }];
}

export function suggestUsername(displayName: string | null): string {
  if (!displayName) return "";
  const cleaned = displayName
    .toLowerCase()
    .replace(/[^a-z0-9_-]/g, "")
    .slice(0, 20);
  return cleaned.length >= 3 ? cleaned : "";
}

export function safeRedirectTo(value: string | null): string {
  if (!value) return "/";
  return value.startsWith("/") && !value.startsWith("//") ? value : "/";
}

export async function loader({ request }: Route.LoaderArgs) {
  const session = await auth.api.getSession({ headers: request.headers });
  if (!session) return redirect("/login");
  const user = await findUserById(session.user.id);
  if (!user) return redirect("/login");
  if (user.username) return redirect("/");
  const redirectTo = safeRedirectTo(new URL(request.url).searchParams.get("redirectTo"));
  return { suggestion: suggestUsername(user.displayName), redirectTo };
}

export async function action({ request }: Route.ActionArgs) {
  const session = await auth.api.getSession({ headers: request.headers });
  if (!session) return redirect("/login");

  const formData = await request.formData();
  const username = (formData.get("username") as string | null)?.trim() ?? "";
  const redirectTo = safeRedirectTo(formData.get("redirectTo") as string | null);

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

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

  try {
    await updateUser(session.user.id, { username });
  } catch {
    return { error: "That username is already taken.", redirectTo };
  }

  return redirect(redirectTo);
}

export default function OnboardingPage({ loaderData, actionData }: Route.ComponentProps) {
  const redirectTo = actionData && "redirectTo" in actionData ? actionData.redirectTo : loaderData.redirectTo;

  return (
    <div className="min-h-screen flex items-center justify-center p-4">
      <Card className="w-full max-w-md">
        <CardHeader className="space-y-1">
          <CardTitle className="text-2xl">Choose a username</CardTitle>
          <CardDescription>
            Pick a username that will be shown to other players. You can change it later in Settings.
          </CardDescription>
        </CardHeader>
        <CardContent>
          <Form method="post" className="space-y-4">
            <input type="hidden" name="redirectTo" value={redirectTo} />
            <div className="space-y-2">
              <Label htmlFor="username">Username</Label>
              <Input
                id="username"
                name="username"
                type="text"
                defaultValue={loaderData.suggestion}
                placeholder="e.g. fantasy_king"
                minLength={3}
                maxLength={30}
                autoFocus
                autoComplete="off"
                aria-describedby={actionData && "error" in actionData ? "onboarding-error" : "username-hint"}
              />
              <p id="username-hint" className="text-xs text-muted-foreground">
                3–30 characters. Letters, numbers, underscores, and hyphens only.
              </p>
            </div>
            {actionData && "error" in actionData && (
              <p id="onboarding-error" role="alert" className="text-sm text-destructive">{actionData.error}</p>
            )}
            <Button type="submit" className="w-full">
              Continue
            </Button>
          </Form>
        </CardContent>
      </Card>
    </div>
  );
}
