import { Injectable, NestMiddleware, UnauthorizedException } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { ConfigService } from '@nestjs/config';
import { JwtHelper } from './jwt.helper';
import { AagService } from '@nxtoai/aag';
import { JwtService } from './jwt.service';

@Injectable()
export class AuthMiddleware implements NestMiddleware {
    constructor(
        private readonly configService: ConfigService,
        private readonly jwtService: JwtService,
        private readonly jwtHelper: JwtHelper,
        private readonly aag: AagService
    ) {}

    async use(req: Request, res: Response, next: NextFunction) {
        const skipJwtEndpoints = this.configService.get<string[]>('JWTETTE_MODULE_OPTIONS.skipJwtEndpoints') || [];
        const path = req.path;
        const method = req.method;
        const endpoint = `${method}:${path}`;

        // Check if the endpoint should skip JWT validation
        if (skipJwtEndpoints.includes(path) || skipJwtEndpoints.includes(endpoint)) {
            this.aag.debug(`Skipping JWT validation for endpoint: ${endpoint}`);
            return next();
        }

        const authHeader = req.headers.authorization;
        if (!authHeader) {
            this.aag.warn(`No authorization header found for endpoint: ${endpoint}`);
            throw new UnauthorizedException('No authorization header');
        }

        const [type, token] = authHeader.split(' ');
        if (type !== 'Bearer' || !token) {
            this.aag.warn(`Invalid authorization header format for endpoint: ${endpoint}`);
            throw new UnauthorizedException('Invalid authorization header format');
        }

        try {
            // Verify token
            const payload = this.jwtService.verify(token);
            
            // Check if token is blacklisted
            const isBlacklisted = await this.jwtHelper.isTokenBlacklisted(token);
            if (isBlacklisted) {
                this.aag.warn(`Blacklisted token used for endpoint: ${endpoint}`);
                throw new UnauthorizedException('Token has been invalidated');
            }

            // Attach user to request
            req['user'] = payload;
            this.aag.debug(`JWT validation successful for endpoint: ${endpoint}`);
            next();
        } catch (error) {
            this.aag.error(`JWT validation failed for endpoint: ${endpoint}`, error.stack);
            throw new UnauthorizedException('Invalid token');
        }
    }
} 