// Server-only permission logic.
// Imports createClient from @/lib/supabase/server — do NOT import this in client components.
// For shared types and pure functions usable in client components, import from './permissions-shared'.

export type { RoleCode, UserSession } from './permissions-shared'
export {
  hasPermission,
  hasAnyPermission,
  hasAllPermissions,
  isAtLeastRole,
  canManageUser,
} from './permissions-shared'

import { createClient } from '@/lib/supabase/server'
import type { UserSession, RoleCode } from './permissions-shared'

export async function getUserSession(): Promise<UserSession | null> {
  const supabase = await createClient()

  const { data: claimsData } = await supabase.auth.getClaims()
  if (!claimsData?.claims) return null

  const authUserId = claimsData.claims.sub

  const { data: profile, error: profileError } = await supabase
    .from('user_profiles')
    .select(`
      id,
      auth_user_id,
      first_name,
      last_name,
      display_name,
      email,
      avatar_url,
      department_id,
      must_change_password,
      account_status,
      role_id,
      roles ( code )
    `)
    .eq('auth_user_id', authUserId)
    .is('deleted_at', null)
    .single()

  if (profileError || !profile) return null
  // tdd-guard:skip — server-only auth session assembly; behaviour is covered by
  // the API-route permission tests (GAP-03 / Batch 6), not a unit sibling here.
  // Block every non-active account state, not just 'deactivated'. A profile in
  // 'locked', 'inactive' or 'deleted' must not yield a usable session even when
  // the underlying Supabase auth user is still valid.
  const BLOCKED_ACCOUNT_STATES = ['deactivated', 'locked', 'inactive', 'deleted']
  if (BLOCKED_ACCOUNT_STATES.includes(profile.account_status as string)) return null

  const rolesRaw = profile.roles as { code: string } | { code: string }[] | null
  const roleData = Array.isArray(rolesRaw) ? (rolesRaw[0] ?? null) : rolesRaw
  const roleCode = (roleData?.code ?? 'readonly') as RoleCode

  const { data: rolePerms } = await supabase
    .from('role_permissions')
    .select('permissions ( code )')
    .eq('role_id', profile.role_id)

  type PermRow = { permissions: { code: string } | { code: string }[] | null }
  const permissions: string[] = (rolePerms as PermRow[] ?? [])
    .map((rp) => {
      const p = rp.permissions
      if (!p) return undefined
      return Array.isArray(p) ? p[0]?.code : p.code
    })
    .filter((c): c is string => typeof c === 'string')

  return {
    userId:              profile.id as string,
    authUserId:          profile.auth_user_id as string,
    roleId:              profile.role_id as string,
    role:                roleCode,
    permissions,
    displayName:         profile.display_name as string,
    firstName:           profile.first_name as string,
    lastName:            profile.last_name as string,
    email:               profile.email as string,
    avatarUrl:           (profile.avatar_url as string | null) ?? null,
    departmentId:        (profile.department_id as string | null) ?? null,
    mustChangePassword:  profile.must_change_password as boolean,
    accountStatus:       profile.account_status as string,
  }
}
