"use server";

import { revalidatePath } from "next/cache";
import { z } from "zod";
import { requireAdmin } from "@/lib/auth";
import { ROLES, ROUTES } from "@/lib/constants";
import { createAdminClient } from "@/lib/supabase/admin";
import { createClient } from "@/lib/supabase/server";
import { getDashboardScopeForCountries } from "@/lib/regions";

const updateAccessSchema = z.object({
  userId: z.string().uuid(),
  role: z.enum([ROLES.admin, ROLES.affiliate]),
  countryIds: z.array(z.coerce.number().int().positive()),
});

const createUserSchema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
  role: z.enum([ROLES.admin, ROLES.affiliate]),
  countryIds: z.array(z.coerce.number().int().positive()),
});

export async function updateUserAccessAction(formData: FormData) {
  await requireAdmin();
  const supabase = await createClient();

  const parsed = updateAccessSchema.safeParse({
    userId: formData.get("user_id"),
    role: formData.get("role"),
    countryIds: formData.getAll("country_ids"),
  });

  if (!parsed.success) {
    throw new Error(parsed.error.issues[0]?.message ?? "Invalid form data.");
  }

  const { userId, role } = parsed.data;
  const countryIds = [...new Set(parsed.data.countryIds)];

  if (role === ROLES.affiliate && countryIds.length > 0) {
    const { data: countries, error: countriesError } = await supabase
      .from("countries")
      .select("id, code")
      .in("id", countryIds);
    if (countriesError) throw new Error(countriesError.message);

    const selectedCodes = (countries ?? []).map((row) => String(row.code ?? "").toUpperCase());
    const scopedDashboard = getDashboardScopeForCountries(selectedCodes);

    if (!scopedDashboard) {
      throw new Error(
        "Affiliate access must be assigned within a single dashboard scope (OPSA, DACH, OPSAB, OPUK, OPIT, OPFS, OPEL).",
      );
    }
  }

  const { error: profileError } = await supabase.from("profiles").update({ role }).eq("id", userId);
  if (profileError) throw new Error(profileError.message);

  const { error: deleteError } = await supabase.from("user_country_access").delete().eq("user_id", userId);
  if (deleteError) throw new Error(deleteError.message);

  if (role === ROLES.affiliate && countryIds.length > 0) {
    const rows = countryIds.map((countryId) => ({ user_id: userId, country_id: countryId }));
    const { error: insertError } = await supabase.from("user_country_access").insert(rows);
    if (insertError) throw new Error(insertError.message);
  }

  revalidatePath(ROUTES.adminUsers);
}

export async function createUserAction(formData: FormData) {
  await requireAdmin();
  const parsed = createUserSchema.safeParse({
    email: formData.get("email"),
    password: formData.get("password"),
    role: formData.get("role"),
    countryIds: formData.getAll("country_ids"),
  });

  if (!parsed.success) {
    throw new Error(parsed.error.issues[0]?.message ?? "Invalid form data.");
  }

  const { email, password, role } = parsed.data;
  const countryIds = [...new Set(parsed.data.countryIds)];
  const adminClient = createAdminClient();
  const userClient = await createClient();

  if (role === ROLES.affiliate && countryIds.length > 0) {
    const { data: countries, error: countriesError } = await userClient
      .from("countries")
      .select("id, code")
      .in("id", countryIds);
    if (countriesError) throw new Error(countriesError.message);

    const selectedCodes = (countries ?? []).map((row) => String(row.code ?? "").toUpperCase());
    const scopedDashboard = getDashboardScopeForCountries(selectedCodes);

    if (!scopedDashboard) {
      throw new Error(
        "Affiliate access must be assigned within a single dashboard scope (OPSA, DACH, OPSAB, OPUK, OPIT, OPFS, OPEL).",
      );
    }
  }

  const { data: authData, error: createError } = await adminClient.auth.admin.createUser({
    email,
    password,
    email_confirm: true,
  });
  if (createError) throw new Error(createError.message);

  const userId = authData.user?.id;
  if (!userId) throw new Error("Auth user creation failed.");

  const { error: profileError } = await userClient
    .from("profiles")
    .update({ role, email })
    .eq("id", userId);
  if (profileError) throw new Error(profileError.message);

  if (role === ROLES.affiliate && countryIds.length > 0) {
    const rows = countryIds.map((countryId) => ({ user_id: userId, country_id: countryId }));
    const { error: insertError } = await userClient.from("user_country_access").insert(rows);
    if (insertError) throw new Error(insertError.message);
  }

  revalidatePath(ROUTES.adminUsers);
}
