import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';

export interface AuthRequest extends FastifyRequest {
  user?: {
    id: string;
    email: string;
    role: string;
    organizationId?: string;
  };
  apiKey?: string;
  authType: 'jwt' | 'api-key' | 'anonymous';
}

export async function authMiddleware(fastify: FastifyInstance) {
  // Authentication hook
  fastify.addHook('onRequest', async (request: FastifyRequest, reply: FastifyReply) => {
    const authReq = request as AuthRequest;
    // Skip auth for health checks and root
    const publicRoutes = ['/', '/health', '/extension/auth'];
    if (publicRoutes.some((route) => request.url.startsWith(route))) {
      authReq.authType = 'anonymous';
      return;
    }

    // Try JWT authentication first
    const authHeader = request.headers.authorization;
    if (authHeader?.startsWith('Bearer ')) {
      const token = authHeader.slice(7);
      try {
        // In production, decode and verify JWT
        // For now, we'll attach a placeholder user
        authReq.user = {
          id: 'user-placeholder',
          email: 'user@example.com',
          role: 'user',
        };
        authReq.authType = 'jwt';
        return;
      } catch (err) {
        // JWT invalid, continue to API key check
      }
    }

    // Try API key authentication
    const apiKey = request.headers['x-api-key'] as string | undefined;
    if (apiKey) {
      // In production, validate API key against database
      authReq.apiKey = apiKey;
      const apiKeyPrefix = apiKey.slice(0, 8);
      authReq.user = {
        id: `api-${apiKeyPrefix}...`,
        email: `api-${apiKeyPrefix}@services.internal`,
        role: 'service',
      };
      authReq.authType = 'api-key';
      return;
    }

    // No auth found - attach anonymous user
    authReq.authType = 'anonymous';
    authReq.user = {
      id: 'anonymous',
      email: 'anonymous@unknown',
      role: 'anonymous',
    };
  });

  // Create auth decorator for route-level protection
  fastify.decorate('requireAuth', async (request: AuthRequest) => {
    if (request.authType === 'anonymous') {
      throw { statusCode: 401, message: 'Authentication required' };
    }
    return true;
  });

  fastify.decorate('requireRole', (allowedRoles: string[]) => {
    return async (request: AuthRequest) => {
      if (!request.user?.role || !allowedRoles.includes(request.user.role)) {
        throw {
          statusCode: 403,
          message: `Role ${request.user?.role} not in allowed roles: ${allowedRoles.join(', ')}`,
        };
      }
      return true;
    };
  });
}
