// src/middlewares/auth.middleware.js
// 인증 미들웨어

const jwt = require('jsonwebtoken');
const { ApiKey, User } = require('../models');
const logger = require('../config/logger.config');

const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';

/**
 * JWT 토큰 인증 미들웨어
 * Authorization: Bearer <JWT_TOKEN>
 */
exports.authenticateJWT = async (req, res, next) => {
  try {
    const authHeader = req.headers.authorization;

    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return res.status(401).json({
        success: false,
        error: {
          code: 'UNAUTHORIZED',
          message: '인증 토큰이 필요합니다.',
        },
      });
    }

    const token = authHeader.substring(7);

    try {
      const decoded = jwt.verify(token, JWT_SECRET);
      req.user = decoded;
      return next();
    } catch (error) {
      if (error.name === 'TokenExpiredError') {
        return res.status(401).json({
          success: false,
          error: {
            code: 'TOKEN_EXPIRED',
            message: '토큰이 만료되었습니다.',
          },
        });
      }

      return res.status(401).json({
        success: false,
        error: {
          code: 'INVALID_TOKEN',
          message: '유효하지 않은 토큰입니다.',
        },
      });
    }
  } catch (error) {
    return next(error);
  }
};

/**
 * API 키 인증 미들웨어
 * Authorization: Bearer <API_KEY>
 */
exports.authenticateApiKey = async (req, res, next) => {
  try {
    const authHeader = req.headers.authorization;

    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return res.status(401).json({
        error: {
          message: 'API 키가 필요합니다.',
          type: 'invalid_request_error',
          code: 'missing_api_key',
        },
      });
    }

    const apiKeyValue = authHeader.substring(7);

    // API 키 접두사 확인
    const prefix = process.env.API_KEY_PREFIX || 'sk-';
    if (!apiKeyValue.startsWith(prefix)) {
      return res.status(401).json({
        error: {
          message: '유효하지 않은 API 키 형식입니다.',
          type: 'invalid_request_error',
          code: 'invalid_api_key',
        },
      });
    }

    // API 키 조회
    const apiKey = await ApiKey.findByKey(apiKeyValue);

    if (!apiKey) {
      return res.status(401).json({
        error: {
          message: '유효하지 않은 API 키입니다.',
          type: 'invalid_request_error',
          code: 'invalid_api_key',
        },
      });
    }

    // 만료 확인
    if (apiKey.isExpired()) {
      return res.status(401).json({
        error: {
          message: 'API 키가 만료되었습니다.',
          type: 'invalid_request_error',
          code: 'expired_api_key',
        },
      });
    }

    // 사용자 상태 확인
    if (apiKey.user.status !== 'active') {
      return res.status(403).json({
        error: {
          message: '계정이 비활성화되었습니다.',
          type: 'invalid_request_error',
          code: 'account_inactive',
        },
      });
    }

    // 사용 기록 업데이트
    await apiKey.recordUsage();

    // 요청 객체에 사용자 및 API 키 정보 추가
    req.user = {
      id: apiKey.user.id,
      userId: apiKey.user.id,
      email: apiKey.user.email,
      role: apiKey.user.role,
      plan: apiKey.user.plan,
    };
    req.apiKey = apiKey;

    return next();
  } catch (error) {
    logger.error('API 키 인증 오류:', error);
    return next(error);
  }
};

/**
 * 관리자 권한 확인 미들웨어
 */
exports.requireAdmin = (req, res, next) => {
  if (req.user.role !== 'admin') {
    return res.status(403).json({
      success: false,
      error: {
        code: 'FORBIDDEN',
        message: '관리자 권한이 필요합니다.',
      },
    });
  }
  return next();
};

/**
 * JWT 또는 API 키 인증 미들웨어
 * JWT 토큰과 API 키 모두 허용
 */
exports.authenticateAny = async (req, res, next) => {
  try {
    const authHeader = req.headers.authorization;

    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return res.status(401).json({
        success: false,
        error: {
          code: 'UNAUTHORIZED',
          message: '인증이 필요합니다.',
        },
      });
    }

    const token = authHeader.substring(7);
    const prefix = process.env.API_KEY_PREFIX || 'sk-';

    // API 키인 경우
    if (token.startsWith(prefix)) {
      const apiKey = await ApiKey.findByKey(token);

      if (!apiKey) {
        return res.status(401).json({
          error: {
            message: '유효하지 않은 API 키입니다.',
            type: 'invalid_request_error',
            code: 'invalid_api_key',
          },
        });
      }

      if (apiKey.isExpired()) {
        return res.status(401).json({
          error: {
            message: 'API 키가 만료되었습니다.',
            type: 'invalid_request_error',
            code: 'expired_api_key',
          },
        });
      }

      if (apiKey.user.status !== 'active') {
        return res.status(403).json({
          error: {
            message: '계정이 비활성화되었습니다.',
            type: 'invalid_request_error',
            code: 'account_inactive',
          },
        });
      }

      await apiKey.recordUsage();

      req.user = {
        id: apiKey.user.id,
        userId: apiKey.user.id,
        email: apiKey.user.email,
        role: apiKey.user.role,
        plan: apiKey.user.plan,
      };
      req.apiKey = apiKey;

      return next();
    }

    // JWT 토큰인 경우
    try {
      const decoded = jwt.verify(token, JWT_SECRET);
      req.user = decoded;
      return next();
    } catch (error) {
      if (error.name === 'TokenExpiredError') {
        return res.status(401).json({
          success: false,
          error: {
            code: 'TOKEN_EXPIRED',
            message: '토큰이 만료되었습니다.',
          },
        });
      }

      return res.status(401).json({
        success: false,
        error: {
          code: 'INVALID_TOKEN',
          message: '유효하지 않은 토큰입니다.',
        },
      });
    }
  } catch (error) {
    return next(error);
  }
};
