// Admin-only helpers. Every call is RLS-gated server-side via the
// `current_user_is_admin()` helper + admin-specific policies. Non-admins
// trying to call these still get clean PostgREST 403/empty-result responses.

import type { AppSupabaseClient } from '../supabase/client.js';

// --- Admin settings -------------------------------------------------------

export interface AdminSetting {
  key: string;
  value: unknown;
  updatedAt: string;
}

export async function listAdminSettings(client: AppSupabaseClient): Promise<AdminSetting[]> {
  const { data, error } = await client
    .from('admin_settings')
    .select('key, value, updated_at')
    .order('key', { ascending: true });
  if (error) throw error;
  return (data ?? []).map((r) => ({ key: r.key, value: r.value, updatedAt: r.updated_at }));
}

export async function updateAdminSetting(
  client: AppSupabaseClient,
  key: string,
  value: unknown,
): Promise<void> {
  const { error } = await client
    .from('admin_settings')
    .upsert(
      {
        key,
        value: value as never,
        updated_at: new Date().toISOString(),
      } as never,
      { onConflict: 'key' },
    );
  if (error) throw error;
}

// --- Invite codes ---------------------------------------------------------

export interface InviteRecord {
  code: string;
  createdBy: string | null;
  usesLimit: number | null;
  usesCount: number;
  expiresAt: string | null;
  disabled: boolean;
  createdAt: string;
}

function mapInvite(row: {
  code: string;
  created_by: string | null;
  uses_limit: number | null;
  uses_count: number;
  expires_at: string | null;
  disabled: boolean;
  created_at: string;
}): InviteRecord {
  return {
    code: row.code,
    createdBy: row.created_by,
    usesLimit: row.uses_limit,
    usesCount: row.uses_count,
    expiresAt: row.expires_at,
    disabled: row.disabled,
    createdAt: row.created_at,
  };
}

export async function listInvites(client: AppSupabaseClient): Promise<InviteRecord[]> {
  const { data, error } = await client
    .from('invites')
    .select('code, created_by, uses_limit, uses_count, expires_at, disabled, created_at')
    .order('created_at', { ascending: false });
  if (error) throw error;
  return (data ?? []).map(mapInvite);
}

export interface CreateInviteParams {
  code?: string; // omit to auto-generate
  usesLimit?: number | null;
  expiresAt?: string | null; // ISO
}

const INVITE_ALPHABET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
function randomCode(length = 10): string {
  const buf =
    typeof crypto !== 'undefined' && 'getRandomValues' in crypto
      ? crypto.getRandomValues(new Uint8Array(length))
      : null;
  let out = '';
  for (let i = 0; i < length; i++) {
    const v = buf ? buf[i]! : Math.floor(Math.random() * 256);
    const ch = INVITE_ALPHABET[v % INVITE_ALPHABET.length];
    if (ch !== undefined) out += ch;
  }
  return out;
}

export async function createInvite(
  client: AppSupabaseClient,
  params: CreateInviteParams = {},
): Promise<InviteRecord> {
  const { data: session, error: aErr } = await client.auth.getUser();
  if (aErr) throw aErr;
  if (!session.user) throw new Error('not authenticated');

  const code = params.code?.trim() || randomCode(10);
  const { data, error } = await client
    .from('invites')
    .insert({
      code,
      created_by: session.user.id,
      uses_limit: params.usesLimit ?? null,
      expires_at: params.expiresAt ?? null,
      disabled: false,
    } as never)
    .select('code, created_by, uses_limit, uses_count, expires_at, disabled, created_at')
    .single();
  if (error) throw error;
  return mapInvite(data as never);
}

export async function setInviteDisabled(
  client: AppSupabaseClient,
  code: string,
  disabled: boolean,
): Promise<void> {
  const { error } = await client
    .from('invites')
    .update({ disabled } as never)
    .eq('code', code);
  if (error) throw error;
}

export async function deleteInvite(client: AppSupabaseClient, code: string): Promise<void> {
  const { error } = await client.from('invites').delete().eq('code', code);
  if (error) throw error;
}

// --- User admin ops -------------------------------------------------------

export interface AdminProfileRow {
  userId: string;
  username: string;
  displayName: string;
  isAdmin: boolean;
  banned: boolean;
  blockedFromInviting: boolean;
  createdAt: string;
}

export async function listAllProfiles(client: AppSupabaseClient): Promise<AdminProfileRow[]> {
  const { data, error } = await client
    .from('profiles')
    .select('user_id, username, display_name, is_admin, banned, blocked_from_inviting, created_at')
    .order('created_at', { ascending: false });
  if (error) throw error;
  return (data ?? []).map((r) => ({
    userId: r.user_id,
    username: r.username,
    displayName: r.display_name,
    isAdmin: r.is_admin,
    banned: r.banned,
    blockedFromInviting: r.blocked_from_inviting,
    createdAt: r.created_at,
  }));
}

export type AdminProfileFlag = 'is_admin' | 'banned' | 'blocked_from_inviting';

export async function setUserFlag(
  client: AppSupabaseClient,
  userId: string,
  flag: AdminProfileFlag,
  value: boolean,
): Promise<void> {
  const patch: Record<string, boolean> = {};
  patch[flag] = value;
  const { error } = await client
    .from('profiles')
    .update(patch as never)
    .eq('user_id', userId);
  if (error) throw error;
}
