import { TenantTier } from '@zync/types'
import type { SessionPayload, TenantId, UserId, UserRole } from '@zync/types'

/**
 * Base session claims shape (legacy interface, retained for compatibility).
 * The canonical session payload is `SessionPayload` from `@zync/types`.
 */
export interface Session {
  sub: UserId
  tenantId: TenantId
  role: UserRole
  iat: number
  exp: number
}

/** Name of the access-session cookie. Locked by foundation-auth-rbac. */
export const SESSION_COOKIE_NAME = 'zync_session'

/**
 * Cookie attributes for the `zync_session` access cookie.
 * HttpOnly + Secure + SameSite=Strict + domain=.zync.is (shared across
 * app.zync.is / admin.zync.is / api.zync.is).
 */
export const SESSION_COOKIE_OPTS = {
  name: SESSION_COOKIE_NAME,
  httpOnly: true,
  secure: true,
  sameSite: 'Strict' as const,
  domain: '.zync.is',
  path: '/',
} as const

/**
 * Expand a user + tenant + permission set into the flat `SessionPayload` JWT
 * claims (minus exp/iat, which jose stamps at sign time).
 *
 * For admin / no-tenant sessions (`tenant === null`) `tid` is null and `tier`
 * defaults to FREELANCER (SessionPayload.tier is non-nullable; tier is only
 * meaningful for tenant-scoped sessions and is ignored for admins).
 */
export function buildSessionPayload(args: {
  user: { id: UserId }
  tenant: { id: TenantId; tier: TenantTier; slug: string } | null
  role: string
  permissions: string[]
  version: number
  type: 'user' | 'admin'
  /** auth-2fa: from tenants.enforce_2fa at token issue time. Default false. */
  enforce2fa?: boolean
  /** auth-2fa: true if the second factor was verified in this session. Default false. */
  twoFactorVerified?: boolean
}): Omit<SessionPayload, 'exp' | 'iat'> {
  return {
    sub: args.user.id,
    tid: args.tenant ? args.tenant.id : null,
    role: args.role,
    permissions: args.permissions,
    tier: args.tenant ? args.tenant.tier : TenantTier.FREELANCER,
    type: args.type,
    v: args.version,
    enforce_2fa: args.enforce2fa ?? false,
    two_factor_verified: args.twoFactorVerified ?? false,
  }
}

/**
 * Extract the raw `zync_session` token from a Cookie header.
 * Returns null when the header is absent or the cookie is missing.
 */
export function parseSessionCookie(cookieHeader: string | null | undefined): string | null {
  if (!cookieHeader) return null
  for (const part of cookieHeader.split(';')) {
    const eq = part.indexOf('=')
    if (eq === -1) continue
    const name = part.slice(0, eq).trim()
    if (name === SESSION_COOKIE_NAME) {
      return decodeURIComponent(part.slice(eq + 1).trim())
    }
  }
  return null
}
