import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import { UserContext, UserRole, Permission } from '../services/rbac.service';

/**
 * Extended Request interface with user data
 */
export interface AuthenticatedRequest extends Request {
  user?: UserContext;
}

/**
 * Authentication middleware
 * Validates JWT tokens and attaches user data to request
 */
export function authMiddleware(
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
): void {
  try {
    // Get token from header
    const authHeader = req.headers.authorization;
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      // For development, allow requests without auth
      if (process.env.NODE_ENV === 'development') {
        req.user = {
          id: 'dev-user',
          email: 'dev@example.com',
          role: UserRole.ADMIN,
          permissions: [Permission.CREATE_TASK, Permission.UPDATE_TASK, Permission.DELETE_TASK],
        };
        return next();
      }
      
      res.status(401).json({
        success: false,
        error: 'No token provided',
      });
      return;
    }

    const token = authHeader.substring(7);
    const secret = process.env.JWT_SECRET || 'development-secret';

    // Verify token
    const decoded = jwt.verify(token, secret) as any;
    
    // Attach user to request
    req.user = {
      id: decoded.id || decoded.sub,
      email: decoded.email,
      role: decoded.role || UserRole.VIEWER,
      permissions: decoded.permissions || [Permission.READ_TASK],
    };

    next();
  } catch (error) {
    console.error('Auth middleware error:', error);
    res.status(401).json({
      success: false,
      error: 'Invalid token',
    });
  }
}

/**
 * Optional authentication middleware
 * Validates token if present but doesn't require it
 */
export function optionalAuthMiddleware(
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
): void {
  try {
    const authHeader = req.headers.authorization;
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return next();
    }

    const token = authHeader.substring(7);
    const secret = process.env.JWT_SECRET || 'development-secret';

    const decoded = jwt.verify(token, secret) as any;
    
    req.user = {
      id: decoded.id || decoded.sub,
      email: decoded.email,
      role: decoded.role || UserRole.VIEWER,
      permissions: decoded.permissions || [Permission.READ_TASK],
    };

    next();
  } catch (error) {
    // Token is invalid but we continue anyway since auth is optional
    next();
  }
}