import { redirect } from "next/navigation";
import { cookies } from "next/headers";
import { ROLES, ROUTES } from "@/lib/constants";
import { env } from "@/lib/env";
import { getDashboardScopeForCountries, getRegionCodes, getRegionMembers } from "@/lib/regions";
import { createClient } from "@/lib/supabase/server";
import type { AppRole } from "@/lib/constants";
import type { ViewerContext } from "@/lib/types";

async function fetchAllowedCountries(userId: string) {
  const supabase = await createClient();

  const { data, error } = await supabase
    .from("user_country_access")
    .select("countries(code)")
    .eq("user_id", userId);

  if (error) {
    throw new Error(error.message);
  }

  return (
    data
      ?.map((row) => {
        const country = row.countries as { code?: string } | null;
        return country?.code?.toUpperCase() ?? null;
      })
      .filter((code): code is string => Boolean(code)) ?? []
  );
}

export async function getViewerContext(): Promise<ViewerContext> {
  const context = await getViewerContextOrNull();
  if (!context) {
    redirect(ROUTES.login);
  }
  return context;
}

export async function getViewerContextOrNull(): Promise<ViewerContext | null> {
  if (env.disableAuth) {
    const regionCodes = getRegionCodes();
    const cookieStore = await cookies();
    const cookieRole = (cookieStore.get("local_viewer_role")?.value ?? "").trim().toLowerCase();
    const hasValidRole = cookieRole === ROLES.affiliate || cookieRole === ROLES.admin;
    if (!hasValidRole) {
      return null;
    }
    const role = cookieRole;
    const cookieScope = (cookieStore.get("local_viewer_scope")?.value ?? "").trim().toUpperCase();
    const scopedFromCookie = regionCodes.includes(cookieScope) ? cookieScope : "";
    const activeScope = role === ROLES.affiliate ? scopedFromCookie : "";
    if (role === ROLES.affiliate && !activeScope) {
      return null;
    }
    const allowedCountries =
      role === ROLES.affiliate
        ? activeScope
          ? getRegionMembers(activeScope)
          : []
        : [];

    return {
      userId: "00000000-0000-0000-0000-000000000000",
      email: role === ROLES.admin ? "local-admin@internal" : "local-regional-manager@internal",
      role,
      allowedCountries,
    };
  }

  const supabase = await createClient();
  const {
    data: { user },
  } = await supabase.auth.getUser();

  if (!user) {
    return null;
  }

  const { data: profile, error } = await supabase
    .from("profiles")
    .select("email, role")
    .eq("id", user.id)
    .maybeSingle();

  if (error) {
    throw new Error(error.message);
  }

  const role = (profile?.role ?? ROLES.affiliate) as AppRole;
  const fetchedCountries = role === ROLES.admin ? [] : await fetchAllowedCountries(user.id);
  const scope = role === ROLES.affiliate ? getDashboardScopeForCountries(fetchedCountries) : null;
  const allowedCountries =
    role === ROLES.affiliate
      ? scope
        ? getRegionMembers(scope).filter((code) => fetchedCountries.includes(code))
        : []
      : [];

  return {
    userId: user.id,
    email: profile?.email ?? user.email ?? "",
    role,
    allowedCountries,
  };
}

export async function requireAdmin() {
  const context = await getViewerContext();
  if (context.role !== ROLES.admin) {
    redirect(ROUTES.dashboard);
  }
  return context;
}

export async function ensureCountryAccess(countryCodes: string[], viewer: ViewerContext) {
  if (viewer.role === ROLES.admin) return;

  const denied = countryCodes.filter(
    (country) => !viewer.allowedCountries.includes(country.toUpperCase()),
  );

  if (denied.length > 0) {
    throw new Error(`You cannot upload data for: ${denied.join(", ")}`);
  }
}
