/**
 * @ai-summary Fastify admin authorization plugin
 * @ai-context Checks if authenticated user is an admin and enforces access control
 */

import { FastifyPluginAsync, FastifyRequest, FastifyReply, FastifyInstance } from 'fastify';
import fp from 'fastify-plugin';
import { Pool } from 'pg';
import { logger } from '../logging/logger';

declare module 'fastify' {
  interface FastifyInstance {
    requireAdmin: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
  }
}

// Store pool reference for use in handler
let dbPool: Pool | null = null;

export function setAdminGuardPool(pool: Pool): void {
  dbPool = pool;
}

const adminGuardPlugin: FastifyPluginAsync = async (fastify) => {
  // Decorate with requireAdmin function that enforces admin authorization
  fastify.decorate('requireAdmin', async function(this: FastifyInstance, request: FastifyRequest, reply: FastifyReply) {
    try {
      if (typeof this.authenticate !== 'function') {
        logger.error('Admin guard: authenticate handler missing');
        return reply.code(500).send({
          error: 'Internal server error',
          message: 'Authentication handler missing'
        });
      }

      await this.authenticate(request, reply);
      if (reply.sent) {
        return;
      }

      // Ensure user is authenticated first
      if (!request.userContext?.userId) {
        logger.warn('Admin guard: user context missing');
        return reply.code(401).send({
          error: 'Unauthorized',
          message: 'Authentication required'
        });
      }

      // If pool not initialized, return 500
      if (!dbPool) {
        logger.error('Admin guard: database pool not initialized');
        return reply.code(500).send({
          error: 'Internal server error',
          message: 'Admin check unavailable'
        });
      }

      // Check if user is in admin_users table and not revoked
      const query = `
        SELECT auth0_sub, email, role, revoked_at
        FROM admin_users
        WHERE auth0_sub = $1 AND revoked_at IS NULL
        LIMIT 1
      `;

      const result = await dbPool.query(query, [request.userContext.userId]);

      if (result.rows.length === 0) {
        logger.warn('Admin guard: user is not authorized as admin', {
          userId: request.userContext.userId?.substring(0, 8) + '...'
        });
        return reply.code(403).send({
          error: 'Forbidden',
          message: 'Admin access required'
        });
      }

      // Set admin flag in userContext
      request.userContext.isAdmin = true;
      request.userContext.adminRecord = result.rows[0];

      logger.info('Admin guard: admin authorization successful', {
        userId: request.userContext.userId?.substring(0, 8) + '...',
        role: result.rows[0].role
      });
    } catch (error) {
      logger.error('Admin guard: authorization check failed', {
        error: error instanceof Error ? error.message : 'Unknown error',
        userId: request.userContext?.userId?.substring(0, 8) + '...'
      });

      return reply.code(500).send({
        error: 'Internal server error',
        message: 'Admin check failed'
      });
    }
  });
};

export default fp(adminGuardPlugin, {
  name: 'admin-guard-plugin'
});
