/**
 * Auth orchestrator middleware for Fastify
 * Supports multiple authentication modes: api_key, jwt, or mixed
 */

import { FastifyRequest, FastifyReply } from 'fastify';
import { env } from '@4runr/shared';
import { requireApiKey } from './authApiKey.js';
import { requireJwt } from './authJwt.js';

/**
 * Main authentication middleware that orchestrates between API key and JWT
 * based on AUTH_MODE environment variable
 * 
 * Modes:
 * - api_key: Only API key authentication
 * - jwt: Only JWT authentication
 * - mixed: Accept either API key OR JWT
 */
export async function requireAuth(
  request: FastifyRequest,
  reply: FastifyReply
): Promise<void> {
  // Skip auth if disabled
  if (!env.AUTH_ENABLED) {
    return;
  }

  // Skip for health/readiness endpoints and DevKit endpoints
  const url = request.url || '/';
  const path = url.split('?')[0] || '/';
  if (
    path === '/health' ||
    path === '/ready' ||
    path === '/liveness' ||
    path === '/startup' ||
    path === '/metrics' ||
    (path && path.startsWith('/debug/')) ||
    (path && path.startsWith('/devkit/'))
  ) {
    return;
  }

  const authMode = env.AUTH_MODE;

  // API key only mode
  if (authMode === 'api_key') {
    await requireApiKey(request, reply);
    return;
  }

  // JWT only mode
  if (authMode === 'jwt') {
    await requireJwt(request, reply);
    return;
  }

  // Mixed mode - accept either API key or JWT
  if (authMode === 'mixed') {
    const hasApiKey = !!request.headers['x-api-key'];
    const hasBearer = !!request.headers.authorization?.startsWith('Bearer ');

    // If API key is present, validate it
    if (hasApiKey) {
      await requireApiKey(request, reply);
      return;
    }

    // If Bearer token is present, validate it
    if (hasBearer) {
      await requireJwt(request, reply);
      return;
    }

    // Neither credential provided
    reply.status(401).send({
      error: 'unauthorized',
      reason: 'invalid_or_missing_credentials',
      message: 'Authentication required. Provide either x-api-key header or Authorization: Bearer <token>',
    });
    return;
  }

  // Fallback to API key if auth mode is unknown
  await requireApiKey(request, reply);
}

/**
 * Get authenticated identity from request
 * Returns either API key or JWT subject, depending on which was used
 */
export function getAuthIdentity(request: FastifyRequest): string | undefined {
  // Check for API key
  const apiKey = (request as any).apiKey;
  if (apiKey) {
    return `apikey:${apiKey.substring(0, 8)}...`; // Return truncated key
  }

  // Check for JWT
  const auth = (request as any).auth || (request as any).user;
  if (auth) {
    return auth.sub || auth.tenantId || 'jwt:unknown';
  }

  return undefined;
}

/**
 * Check if request is authenticated
 */
export function isAuthenticated(request: FastifyRequest): boolean {
  return !!(
    (request as any).apiKey ||
    (request as any).auth ||
    (request as any).user
  );
}

