/**
 * Resolves the session cookie into the current user.
 * Server-side truth: validity (expiry + revocation) and role come from the DB,
 * never from the client. Exported through the module index so the composition
 * root can inject it into other modules without cross-module imports.
 */
import type { FastifyRequest } from 'fastify';
import type pg from 'pg';
import type { Authenticate, CurrentUser } from '../../../shared/auth.js';
import { AppError } from '../../../shared/errors.js';
import { hashSessionToken } from './session-token.js';
import { SESSION_COOKIE_NAME } from '../api/identity.routes.js';

interface ResolvedRow {
  id: string;
  email: string;
  role: string;
}

const RESOLVE_SQL = `
  SELECT u.id, u.email, u.role
  FROM identity_sessions s
  JOIN identity_users u ON u.id = s.user_id
  WHERE s.token_hash = $1
    AND s.revoked_at IS NULL
    AND s.expires_at > now()
`;

export function createSessionAuthenticator(pool: pg.Pool): Authenticate {
  return async (request: FastifyRequest): Promise<CurrentUser> => {
    const token = request.cookies[SESSION_COOKIE_NAME];
    if (!token) {
      throw new AppError(401, 'UNAUTHORIZED', 'Authentication required');
    }

    const result = await pool.query<ResolvedRow>(RESOLVE_SQL, [hashSessionToken(token)]);
    const row = result.rows[0];
    if (!row) {
      throw new AppError(401, 'UNAUTHORIZED', 'Authentication required');
    }

    return { id: row.id, email: row.email, role: row.role as CurrentUser['role'] };
  };
}
