import { cookies } from 'next/headers'
import type { SupabaseClient } from '@supabase/supabase-js'

export type OrgRole = 'owner' | 'manager' | 'member'

export type EffectiveUser = {
  real_user_id: string
  effective_user_id: string
  email: string
  full_name: string | null
  is_super_admin: boolean
  org_role: OrgRole | null
  is_viewing_as: boolean
  view_as_label: string | null
}

export const VIEW_AS_COOKIE = 'view_as_user_id'

type ProfileRow = {
  id: string
  email: string
  full_name: string | null
  is_super_admin: boolean
}

async function loadProfile(
  supabase: SupabaseClient,
  userId: string,
): Promise<ProfileRow | null> {
  const { data } = await supabase
    .from('profiles')
    .select('id, email, full_name, is_super_admin')
    .eq('id', userId)
    .maybeSingle<ProfileRow>()
  return data ?? null
}

async function loadOrgRole(
  supabase: SupabaseClient,
  orgId: string,
  userId: string,
): Promise<OrgRole | null> {
  const { data } = await supabase
    .from('organization_members')
    .select('role')
    .eq('organization_id', orgId)
    .eq('user_id', userId)
    .maybeSingle<{ role: OrgRole }>()
  return data?.role ?? null
}

/**
 * Compute the "effective user" — who the app should behave as right now.
 * If view_as_user_id cookie is set AND the real user is a super_admin,
 * return the target user's profile/role. Otherwise return the real user.
 *
 * Data access still happens as the real authenticated user (RLS doesn't
 * change). This is purely a UI/permission layer.
 */
export async function getEffectiveUser(
  supabase: SupabaseClient,
  orgId: string,
): Promise<EffectiveUser | null> {
  const {
    data: { user: real },
  } = await supabase.auth.getUser()
  if (!real) return null

  const realProfile = await loadProfile(supabase, real.id)
  if (!realProfile) return null

  const cookieStore = await cookies()
  const viewAsId = cookieStore.get(VIEW_AS_COOKIE)?.value

  if (viewAsId && viewAsId !== real.id && realProfile.is_super_admin) {
    const target = await loadProfile(supabase, viewAsId)
    if (target) {
      const role = await loadOrgRole(supabase, orgId, target.id)
      return {
        real_user_id: real.id,
        effective_user_id: target.id,
        email: target.email,
        full_name: target.full_name,
        is_super_admin: target.is_super_admin,
        org_role: role,
        is_viewing_as: true,
        view_as_label: target.full_name || target.email,
      }
    }
  }

  const role = await loadOrgRole(supabase, orgId, real.id)
  return {
    real_user_id: real.id,
    effective_user_id: real.id,
    email: realProfile.email,
    full_name: realProfile.full_name,
    is_super_admin: realProfile.is_super_admin,
    org_role: role,
    is_viewing_as: false,
    view_as_label: null,
  }
}

/**
 * Sentinel UUID used as a "matches nothing" filter so PostgREST queries
 * return zero rows when the effective user has no imports.
 */
const NO_MATCH_UUID = '00000000-0000-0000-0000-000000000000'

/**
 * Mirrors what RLS on `teams` would return for the *effective* user.
 * Use it to filter a `listVisibleTeams` result (loaded under the real
 * JWT) down to what the view-as target would actually see.
 *
 * - View-as off, or effective user is an owner / super_admin → all teams.
 * - Otherwise → only teams owned by the effective user.
 */
export function filterTeamsForViewAs<T extends { owner_user_id: string }>(
  teams: T[],
  eu: EffectiveUser | null,
): T[] {
  if (!eu || !eu.is_viewing_as) return teams
  if (eu.is_super_admin || eu.org_role === 'owner') return teams
  return teams.filter((t) => t.owner_user_id === eu.effective_user_id)
}

/**
 * Returns the list of `clockify_imports.id`s the effective user is allowed
 * to see right now, mirroring the time_entries RLS policy at the app layer.
 *
 * - If view-as is OFF: returns `null` — RLS already enforces the JWT user's
 *   visibility correctly. No extra scoping needed.
 * - If view-as is ON and the effective user is an owner / super_admin:
 *   returns `null` — they'd see everything under RLS too.
 * - Otherwise (view-as → manager / member): returns the import IDs where
 *   `imported_by = effective_user_id`, or a sentinel `[NO_MATCH_UUID]` when
 *   the target has no imports. Callers `.in('import_id', ids)` on
 *   `time_entries`, or `.in('id', ids)` on `clockify_imports`.
 *
 * **Why this exists:** RLS keys off `auth.uid()` (the real JWT user), so a
 * super-admin viewing-as Adi would otherwise still see all data because the
 * underlying queries still run as the super-admin. This helper enforces the
 * would-be-Adi visibility at the application layer.
 */
export async function getViewAsImportScope(
  supabase: SupabaseClient,
  orgId: string,
  eu: EffectiveUser | null,
): Promise<string[] | null> {
  if (!eu || !eu.is_viewing_as) return null
  if (eu.is_super_admin || eu.org_role === 'owner') return null

  const { data } = await supabase
    .from('clockify_imports')
    .select('id')
    .eq('org_id', orgId)
    .eq('imported_by', eu.effective_user_id)
    .returns<{ id: string }[]>()
  const ids = (data ?? []).map((r) => r.id)
  return ids.length === 0 ? [NO_MATCH_UUID] : ids
}
