import { redirect } from "next/navigation";
import { hash } from "bcryptjs";
import { prisma } from "@/lib/prisma";
import { SYSTEM_PERMISSIONS } from "@/lib/access";
import { setSession } from "@/lib/session";
import { hasAdminUser } from "@/lib/setup";

export const dynamic = "force-dynamic";

function normalizeUsername(value: FormDataEntryValue | null) {
  return String(value || "")
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9_-]/g, "");
}

async function createFirstAdmin(formData: FormData) {
  "use server";

  const username = normalizeUsername(formData.get("username"));
  const password = String(formData.get("password") || "");

  if (!username || password.length < 10) {
    redirect("/setup?error=invalid");
  }

  const existingAdmin = await prisma.userRole.findFirst({
    where: { role: { name: "admin" } },
    select: { userId: true }
  });

  if (existingAdmin) {
    redirect("/login");
  }

  const existingUser = await prisma.user.findUnique({
    where: { username },
    select: { id: true }
  });

  if (existingUser) {
    redirect("/setup?error=username");
  }

  const passwordHash = await hash(password, 12);

  const user = await prisma.$transaction(async (tx) => {
    const permissions = await Promise.all(
      SYSTEM_PERMISSIONS.map((key) =>
        tx.permission.upsert({
          where: { key },
          update: {},
          create: { key, description: key }
        })
      )
    );

    const adminRole = await tx.role.upsert({
      where: { name: "admin" },
      update: {},
      create: {
        name: "admin",
        description: "Full system administrator"
      }
    });

    await Promise.all(
      permissions.map((permission) =>
        tx.rolePermission.upsert({
          where: { roleId_permissionId: { roleId: adminRole.id, permissionId: permission.id } },
          update: {},
          create: { roleId: adminRole.id, permissionId: permission.id }
        })
      )
    );

    const createdUser = await tx.user.create({
      data: {
        username,
        displayName: username,
        passwordHash
      }
    });

    await tx.userRole.create({ data: { userId: createdUser.id, roleId: adminRole.id } });
    await tx.room.create({
      data: {
        slug: `@${username}`,
        name: `${username}'s room`,
        ownerId: createdUser.id,
        isPersonal: true,
        visibility: "FRIENDS"
      }
    });

    return createdUser;
  });

  await setSession(user.id);
  redirect("/dashboard");
}

export default async function SetupPage({ searchParams }: { searchParams: Promise<{ error?: string }> }) {
  if (await hasAdminUser()) {
    redirect("/login");
  }
  const { error } = await searchParams;

  return (
    <main className="auth-page">
      <section className="auth-shell setup-shell">
        <div className="auth-intro">
          <span className="brand-mark" aria-hidden="true" />
          <div className="title-block">
            <h1>First Setup</h1>
            <p>Create the first administrator, seed permissions, and create the initial persistent room.</p>
          </div>
          <div className="setup-checklist">
            <div><span /> Admin role and permissions</div>
            <div><span /> First user account</div>
            <div><span /> Personal room route</div>
            <div><span /> Setup lockout after completion</div>
          </div>
        </div>
        <section className="auth-card">
          <div className="title-block" style={{ marginBottom: 18 }}>
            <h1>Administrator</h1>
            <p>This screen is only available while no admin user exists.</p>
          </div>
          {error ? <p className="form-error">{setupErrorMessage(error)}</p> : null}
          <form className="form" action={createFirstAdmin}>
            <label>
              Username
              <input className="input" name="username" autoComplete="username" required />
            </label>
            <label>
              Password
              <input className="input" name="password" type="password" autoComplete="new-password" minLength={10} required />
            </label>
            <button className="button primary" type="submit">
              Create admin
            </button>
          </form>
        </section>
      </section>
    </main>
  );
}

function setupErrorMessage(error: string) {
  if (error === "username") return "This username already exists. Choose another username.";
  return "Use a username with letters, numbers, dashes or underscores and a password with at least 10 characters.";
}
