import { NextApiRequest, NextApiResponse } from 'next';
import { verifyToken } from '../auth';
import { UserService } from '../../backend/services/userService';
import { UserDTO } from '../../types';

// Extend NextApiRequest to include user property
export interface AuthenticatedRequest extends NextApiRequest {
    user?: UserDTO;
}

/**
 * Middleware to require authentication
 * Returns 401 if no valid token is found
 */
export async function requireAuth(
    req: AuthenticatedRequest,
    res: NextApiResponse
): Promise<boolean> {
    const token = getTokenFromRequest(req);

    if (!token) {
        res.status(401).json({ success: false, error: 'Authentication required' });
        return false;
    }

    const decoded = verifyToken(token);
    if (!decoded) {
        res.status(401).json({ success: false, error: 'Invalid or expired token' });
        return false;
    }

    // Load user from database
    const user = await UserService.getUserById(decoded.userId);
    if (!user) {
        res.status(401).json({ success: false, error: 'User not found' });
        return false;
    }

    // Check if user is banned
    if (user.status === 'BANNED') {
        res.status(403).json({ success: false, error: 'Account has been banned' });
        return false;
    }

    // Attach user to request
    req.user = user;
    return true;
}

/**
 * Middleware for optional authentication
 * Attaches user to request if valid token exists, but doesn't fail if not
 */
export async function optionalAuth(req: AuthenticatedRequest): Promise<void> {
    const token = getTokenFromRequest(req);

    if (!token) {
        return;
    }

    const decoded = verifyToken(token);
    if (!decoded) {
        return;
    }

    const user = await UserService.getUserById(decoded.userId);
    if (user && user.status !== 'BANNED') {
        req.user = user;
    }
}

/**
 * Extract JWT token from request
 * Checks both cookies and Authorization header
 */
function getTokenFromRequest(req: NextApiRequest): string | null {
    // Check cookie first
    if (req.cookies.token) {
        return req.cookies.token;
    }

    // Check Authorization header
    const authHeader = req.headers.authorization;
    if (authHeader && authHeader.startsWith('Bearer ')) {
        return authHeader.substring(7);
    }

    return null;
}
