/**
 * 슈퍼관리자 권한 검증 미들웨어
 * 회사코드가 '*'인 최고 관리자만 DDL 실행을 허용
 */

import { Request, Response, NextFunction } from "express";
import { logger } from "../utils/logger";

// DDL 요청 시간 추적을 위한 메모리 저장소
const ddlRequestTimes = new Map<string, number>();

// AuthenticatedRequest 타입 확장
export interface AuthenticatedRequest extends Request {
  user?: {
    userId: string;
    userName: string;
    companyCode: string;
    userLang?: string;
  };
}

/**
 * 슈퍼관리자 권한 확인 미들웨어
 * 회사코드가 '*'이고 userId가 'plm_admin'인 사용자만 허용
 */
export const requireSuperAdmin = (
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
): void => {
  try {
    // 인증 여부 확인
    if (!req.user) {
      logger.warn("DDL 실행 시도 - 인증되지 않은 사용자", {
        ip: req.ip,
        userAgent: req.get("User-Agent"),
        url: req.originalUrl,
      });

      res.status(401).json({
        success: false,
        error: {
          code: "AUTHENTICATION_REQUIRED",
          details: "인증이 필요합니다.",
        },
      });
      return;
    }

    // 슈퍼관리자 권한 확인 (회사코드가 '*'인 사용자)
    if (req.user.companyCode !== "*") {
      logger.warn("DDL 실행 시도 - 권한 부족", {
        userId: req.user.userId,
        companyCode: req.user.companyCode,
        ip: req.ip,
        userAgent: req.get("User-Agent"),
        url: req.originalUrl,
      });

      res.status(403).json({
        success: false,
        error: {
          code: "SUPER_ADMIN_REQUIRED",
          details:
            "최고 관리자 권한이 필요합니다. DDL 실행은 회사코드가 '*'인 사용자만 가능합니다.",
        },
      });
      return;
    }

    // 권한 확인 로깅
    logger.info("DDL 실행 권한 확인 완료", {
      userId: req.user.userId,
      companyCode: req.user.companyCode,
      ip: req.ip,
      url: req.originalUrl,
    });

    next();
  } catch (error) {
    logger.error("슈퍼관리자 권한 확인 중 오류 발생:", error);

    res.status(500).json({
      success: false,
      error: {
        code: "AUTHORIZATION_ERROR",
        details: "권한 확인 중 오류가 발생했습니다.",
      },
    });
  }
};

/**
 * DDL 실행 전 추가 보안 검증
 * 세션 유효성 및 사용자 상태 재확인
 */
export const validateDDLPermission = (
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
): void => {
  try {
    const user = req.user!; // requireSuperAdmin을 통과했으므로 user 존재 보장

    // 세션 유효성 재확인
    if (!user.userId || !user.companyCode) {
      logger.error("DDL 실행 - 세션 데이터 불완전", {
        userId: user.userId,
        companyCode: user.companyCode,
      });

      res.status(401).json({
        success: false,
        error: {
          code: "INVALID_SESSION",
          details: "세션 정보가 불완전합니다. 다시 로그인해주세요.",
        },
      });
      return;
    }

    // 추가 보안 체크 - 메모리 기반 요청 시간 간격 제한
    const now = Date.now();
    const minInterval = 5000; // 5초 간격 제한
    const lastDDLTime = ddlRequestTimes.get(user.userId);

    if (lastDDLTime && now - lastDDLTime < minInterval) {
      logger.warn("DDL 실행 - 너무 빈번한 요청", {
        userId: user.userId,
        timeSinceLastDDL: now - lastDDLTime,
      });

      res.status(429).json({
        success: false,
        error: {
          code: "TOO_MANY_REQUESTS",
          details:
            "DDL 실행 요청이 너무 빈번합니다. 잠시 후 다시 시도해주세요.",
        },
      });
      return;
    }

    // 마지막 DDL 실행 시간 기록
    ddlRequestTimes.set(user.userId, now);

    logger.info("DDL 실행 추가 보안 검증 완료", {
      userId: user.userId,
      companyCode: user.companyCode,
    });

    next();
  } catch (error) {
    logger.error("DDL 권한 추가 검증 중 오류 발생:", error);

    res.status(500).json({
      success: false,
      error: {
        code: "VALIDATION_ERROR",
        details: "권한 검증 중 오류가 발생했습니다.",
      },
    });
  }
};

/**
 * 사용자가 슈퍼관리자인지 확인하는 유틸리티 함수
 */
export const isSuperAdmin = (user: AuthenticatedRequest["user"]): boolean => {
  return user?.companyCode === "*";
};

/**
 * DDL 실행 권한 체크 (미들웨어 없이 사용)
 */
export const checkDDLPermission = (
  user: AuthenticatedRequest["user"]
): {
  hasPermission: boolean;
  errorCode?: string;
  errorMessage?: string;
} => {
  if (!user) {
    return {
      hasPermission: false,
      errorCode: "AUTHENTICATION_REQUIRED",
      errorMessage: "인증이 필요합니다.",
    };
  }

  if (!isSuperAdmin(user)) {
    return {
      hasPermission: false,
      errorCode: "SUPER_ADMIN_REQUIRED",
      errorMessage: "최고 관리자 권한이 필요합니다.",
    };
  }

  return { hasPermission: true };
};
