/**
 * Customer portal JWT mint/verify + cookie helpers — tenant-portals (wave 9b, Task 2).
 *
 * Mirrors contractor-session.ts; portal sessions are stateful (DB row required on verify).
 */
import { SignJWT, jwtVerify } from 'jose'
import type { PortalSessionPayload } from './types'

/** Portal session JWT base TTL, in seconds (4 hours). */
export const PORTAL_SESSION_TTL_SECONDS = 60 * 60 * 4

/** Name of the customer portal session cookie. */
export const PORTAL_COOKIE_NAME = 'zync_portal_session'

/**
 * Cookie attributes for the `zync_portal_session` session cookie.
 * HttpOnly + Secure + SameSite=Lax + domain=.zync.is; path=/ (SPA + /api/portal/*).
 */
export const PORTAL_COOKIE_OPTS = {
  name: PORTAL_COOKIE_NAME,
  httpOnly: true,
  secure: true,
  sameSite: 'Lax' as const,
  domain: '.zync.is',
  path: '/',
} as const

/**
 * Sign a customer portal session (HS256). `exp`/`iat` are set by jose;
 * `role` is always `'portal_customer'`.
 */
export async function signPortalSession(
  payload: Omit<PortalSessionPayload, 'iat' | 'exp' | 'role'>,
  secret: string,
  ttlSeconds: number = PORTAL_SESSION_TTL_SECONDS,
): Promise<string> {
  const secretKey = new TextEncoder().encode(secret)
  return new SignJWT({
    ...payload,
    sub: payload.userId,
    portalRole: payload.portalRole,
    role: 'portal_customer',
  })
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuedAt()
    .setExpirationTime(`${ttlSeconds}s`)
    .sign(secretKey)
}

/** Verify a customer portal session JWT. Throws on invalid/expired/tampered token. */
export async function verifyPortalToken(
  token: string,
  secret: string,
): Promise<PortalSessionPayload> {
  const secretKey = new TextEncoder().encode(secret)
  const { payload } = await jwtVerify(token, secretKey)
  return payload as unknown as PortalSessionPayload
}

/**
 * Extract the raw `zync_portal_session` token from a Cookie header.
 * Returns null when the header is absent or the cookie is missing.
 */
export function parsePortalCookie(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 === PORTAL_COOKIE_NAME) {
      return decodeURIComponent(part.slice(eq + 1).trim())
    }
  }
  return null
}
