import { Response } from "express";
import { AuthenticatedRequest } from "../types/auth";
import { ApiResponse } from "../types/common";
import { RoleService } from "../services/roleService";
import { logger } from "../utils/logger";
import {
  isSuperAdmin,
  isCompanyAdmin,
  canAccessCompanyData,
} from "../utils/permissionUtils";
import { auditLogService, getClientIp } from "../services/auditLogService";

/**
 * 권한 그룹 목록 조회
 * - 회사 관리자: 자기 회사 권한 그룹만 조회
 * - 최고 관리자: 모든 회사 권한 그룹 조회 (companyCode 미지정 시 전체 조회)
 */
export const getRoleGroups = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const search = req.query.search as string | undefined;
    const companyCode = req.query.companyCode as string | undefined;

    // 최고 관리자가 아닌 경우 자기 회사만 조회
    let targetCompanyCode: string | undefined;
    if (isSuperAdmin(req.user)) {
      // 최고 관리자: companyCode 파라미터가 있으면 해당 회사만, 없으면 전체 조회
      targetCompanyCode = companyCode;
      logger.info("권한 그룹 목록 조회 (최고 관리자)", {
        userId: req.user?.userId,
        targetCompanyCode: targetCompanyCode || "전체",
        search,
      });
    } else {
      // 일반 관리자: 자기 회사만 조회
      targetCompanyCode = req.user?.companyCode;
      if (!targetCompanyCode) {
        res.status(400).json({
          success: false,
          message: "회사 코드가 필요합니다",
        });
        return;
      }
      logger.info("권한 그룹 목록 조회 (회사 관리자)", {
        userId: req.user?.userId,
        companyCode: targetCompanyCode,
        search,
      });
    }

    const roleGroups = await RoleService.getRoleGroups(
      targetCompanyCode,
      search
    );

    const response: ApiResponse<any[]> = {
      success: true,
      message: "권한 그룹 목록 조회 성공",
      data: roleGroups,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("권한 그룹 목록 조회 실패", { error });
    res.status(500).json({
      success: false,
      message: "권한 그룹 목록 조회 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 권한 그룹 상세 조회
 */
export const getRoleGroupById = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const objid = parseInt(req.params.id, 10);

    if (isNaN(objid)) {
      res.status(400).json({
        success: false,
        message: "유효하지 않은 권한 그룹 ID입니다",
      });
      return;
    }

    const roleGroup = await RoleService.getRoleGroupById(objid);

    if (!roleGroup) {
      res.status(404).json({
        success: false,
        message: "권한 그룹을 찾을 수 없습니다",
      });
      return;
    }

    // 권한 체크: 슈퍼관리자 또는 해당 회사 관리자만 조회 가능
    if (
      !isSuperAdmin(req.user) &&
      !canAccessCompanyData(req.user, roleGroup.companyCode)
    ) {
      res.status(403).json({
        success: false,
        message: "권한이 없습니다",
      });
      return;
    }

    const response: ApiResponse<any> = {
      success: true,
      message: "권한 그룹 상세 조회 성공",
      data: roleGroup,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("권한 그룹 상세 조회 실패", { error });
    res.status(500).json({
      success: false,
      message: "권한 그룹 상세 조회 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 권한 그룹 생성
 * - 회사 관리자: 자기 회사에만 권한 그룹 생성 가능
 * - 최고 관리자: 모든 회사에 권한 그룹 생성 가능
 */
export const createRoleGroup = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { authName, authCode, companyCode } = req.body;

    if (!authName || !authCode || !companyCode) {
      res.status(400).json({
        success: false,
        message: "필수 정보가 누락되었습니다 (authName, authCode, companyCode)",
      });
      return;
    }

    // 권한 체크: 회사 관리자 이상만 생성 가능
    if (!isSuperAdmin(req.user) && !isCompanyAdmin(req.user)) {
      res.status(403).json({
        success: false,
        message: "권한 그룹 생성 권한이 없습니다",
      });
      return;
    }

    // 회사 관리자는 자기 회사에만 권한 그룹 생성 가능
    if (!isSuperAdmin(req.user) && req.user?.companyCode !== companyCode) {
      res.status(403).json({
        success: false,
        message: "다른 회사의 권한 그룹을 생성할 수 없습니다",
      });
      return;
    }

    const roleGroup = await RoleService.createRoleGroup({
      authName,
      authCode,
      companyCode,
      writer: req.user?.userId || "SYSTEM",
    });

    const response: ApiResponse<any> = {
      success: true,
      message: "권한 그룹 생성 성공",
      data: roleGroup,
    };

    auditLogService.log({
      companyCode: companyCode || req.user?.companyCode || "",
      userId: req.user?.userId || "",
      userName: req.user?.userName || "",
      action: "CREATE",
      resourceType: "ROLE",
      resourceId: String(roleGroup?.objid || ""),
      resourceName: authName,
      summary: `권한 그룹 "${authName}" 생성`,
      changes: { after: { authName, authCode, companyCode } },
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.status(201).json(response);
  } catch (error) {
    logger.error("권한 그룹 생성 실패", { error });
    res.status(500).json({
      success: false,
      message: "권한 그룹 생성 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 권한 그룹 수정
 */
export const updateRoleGroup = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const objid = parseInt(req.params.id, 10);
    const { authName, authCode, status } = req.body;

    if (isNaN(objid)) {
      res.status(400).json({
        success: false,
        message: "유효하지 않은 권한 그룹 ID입니다",
      });
      return;
    }

    // 기존 권한 그룹 조회
    const existingRoleGroup = await RoleService.getRoleGroupById(objid);
    if (!existingRoleGroup) {
      res.status(404).json({
        success: false,
        message: "권한 그룹을 찾을 수 없습니다",
      });
      return;
    }

    // 권한 체크
    if (
      !isSuperAdmin(req.user) &&
      !canAccessCompanyData(req.user, existingRoleGroup.companyCode)
    ) {
      res.status(403).json({
        success: false,
        message: "권한 그룹 수정 권한이 없습니다",
      });
      return;
    }

    const roleGroup = await RoleService.updateRoleGroup(objid, {
      authName,
      authCode,
      status,
    });

    const response: ApiResponse<any> = {
      success: true,
      message: "권한 그룹 수정 성공",
      data: roleGroup,
    };

    auditLogService.log({
      companyCode: req.user?.companyCode || "",
      userId: req.user?.userId || "",
      userName: req.user?.userName || "",
      action: "UPDATE",
      resourceType: "ROLE",
      resourceId: String(objid),
      resourceName: authName,
      summary: `권한 그룹 "${authName}" 수정`,
      changes: {
        before: { authName: existingRoleGroup.authName, authCode: existingRoleGroup.authCode, status: existingRoleGroup.status },
        after: { authName, authCode, status },
      },
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.status(200).json(response);
  } catch (error) {
    logger.error("권한 그룹 수정 실패", { error });
    res.status(500).json({
      success: false,
      message: "권한 그룹 수정 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 권한 그룹 삭제
 */
export const deleteRoleGroup = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const objid = parseInt(req.params.id, 10);

    if (isNaN(objid)) {
      res.status(400).json({
        success: false,
        message: "유효하지 않은 권한 그룹 ID입니다",
      });
      return;
    }

    // 기존 권한 그룹 조회
    const existingRoleGroup = await RoleService.getRoleGroupById(objid);
    if (!existingRoleGroup) {
      res.status(404).json({
        success: false,
        message: "권한 그룹을 찾을 수 없습니다",
      });
      return;
    }

    // 권한 체크
    if (
      !isSuperAdmin(req.user) &&
      !canAccessCompanyData(req.user, existingRoleGroup.companyCode)
    ) {
      res.status(403).json({
        success: false,
        message: "권한 그룹 삭제 권한이 없습니다",
      });
      return;
    }

    await RoleService.deleteRoleGroup(objid);

    const response: ApiResponse<null> = {
      success: true,
      message: "권한 그룹 삭제 성공",
      data: null,
    };

    auditLogService.log({
      companyCode: existingRoleGroup.companyCode || req.user?.companyCode || "",
      userId: req.user?.userId || "",
      userName: req.user?.userName || "",
      action: "DELETE",
      resourceType: "ROLE",
      resourceId: String(objid),
      resourceName: existingRoleGroup.authName,
      summary: `권한 그룹 "${existingRoleGroup.authName}" 삭제`,
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.status(200).json(response);
  } catch (error) {
    logger.error("권한 그룹 삭제 실패", { error });
    res.status(500).json({
      success: false,
      message: "권한 그룹 삭제 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 권한 그룹 멤버 목록 조회
 */
export const getRoleMembers = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const masterObjid = parseInt(req.params.id, 10);

    if (isNaN(masterObjid)) {
      res.status(400).json({
        success: false,
        message: "유효하지 않은 권한 그룹 ID입니다",
      });
      return;
    }

    // 기존 권한 그룹 조회
    const roleGroup = await RoleService.getRoleGroupById(masterObjid);
    if (!roleGroup) {
      res.status(404).json({
        success: false,
        message: "권한 그룹을 찾을 수 없습니다",
      });
      return;
    }

    // 권한 체크
    if (
      !isSuperAdmin(req.user) &&
      !canAccessCompanyData(req.user, roleGroup.companyCode)
    ) {
      res.status(403).json({
        success: false,
        message: "권한 그룹 멤버 조회 권한이 없습니다",
      });
      return;
    }

    const members = await RoleService.getRoleMembers(masterObjid);

    const response: ApiResponse<any[]> = {
      success: true,
      message: "권한 그룹 멤버 조회 성공",
      data: members,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("권한 그룹 멤버 조회 실패", { error });
    res.status(500).json({
      success: false,
      message: "권한 그룹 멤버 조회 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 권한 그룹 멤버 추가
 */
export const addRoleMembers = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const masterObjid = parseInt(req.params.id, 10);
    const { userIds } = req.body;

    if (isNaN(masterObjid)) {
      res.status(400).json({
        success: false,
        message: "유효하지 않은 권한 그룹 ID입니다",
      });
      return;
    }

    if (!Array.isArray(userIds) || userIds.length === 0) {
      res.status(400).json({
        success: false,
        message: "추가할 사용자 ID 목록이 필요합니다",
      });
      return;
    }

    // 기존 권한 그룹 조회
    const roleGroup = await RoleService.getRoleGroupById(masterObjid);
    if (!roleGroup) {
      res.status(404).json({
        success: false,
        message: "권한 그룹을 찾을 수 없습니다",
      });
      return;
    }

    // 권한 체크
    if (
      !isSuperAdmin(req.user) &&
      !canAccessCompanyData(req.user, roleGroup.companyCode)
    ) {
      res.status(403).json({
        success: false,
        message: "권한 그룹 멤버 추가 권한이 없습니다",
      });
      return;
    }

    await RoleService.addRoleMembers(
      masterObjid,
      userIds,
      req.user?.userId || "SYSTEM"
    );

    const response: ApiResponse<null> = {
      success: true,
      message: "권한 그룹 멤버 추가 성공",
      data: null,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("권한 그룹 멤버 추가 실패", { error });
    res.status(500).json({
      success: false,
      message: "권한 그룹 멤버 추가 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 권한 그룹 멤버 일괄 업데이트
 */
export const updateRoleMembers = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const masterObjid = parseInt(req.params.id, 10);
    const { userIds } = req.body;

    if (isNaN(masterObjid)) {
      res.status(400).json({
        success: false,
        message: "유효하지 않은 권한 그룹 ID입니다",
      });
      return;
    }

    if (!Array.isArray(userIds)) {
      res.status(400).json({
        success: false,
        message: "사용자 ID 배열이 필요합니다",
      });
      return;
    }

    // 기존 권한 그룹 조회
    const roleGroup = await RoleService.getRoleGroupById(masterObjid);
    if (!roleGroup) {
      res.status(404).json({
        success: false,
        message: "권한 그룹을 찾을 수 없습니다",
      });
      return;
    }

    // 권한 체크
    if (
      !isSuperAdmin(req.user) &&
      !canAccessCompanyData(req.user, roleGroup.companyCode)
    ) {
      res.status(403).json({
        success: false,
        message: "권한 그룹 멤버 수정 권한이 없습니다",
      });
      return;
    }

    // 기존 멤버 조회
    const existingMembers = await RoleService.getRoleMembers(masterObjid);
    const existingUserIds = existingMembers.map((m: any) => m.userId);

    // 추가할 멤버 (새로 추가된 것들)
    const toAdd = userIds.filter((id: string) => !existingUserIds.includes(id));

    // 제거할 멤버 (기존에 있었는데 없어진 것들)
    const toRemove = existingUserIds.filter(
      (id: string) => !userIds.includes(id)
    );

    // 추가
    if (toAdd.length > 0) {
      await RoleService.addRoleMembers(
        masterObjid,
        toAdd,
        req.user?.userId || "SYSTEM"
      );
    }

    // 제거
    if (toRemove.length > 0) {
      await RoleService.removeRoleMembers(
        masterObjid,
        toRemove,
        req.user?.userId || "SYSTEM"
      );
    }

    logger.info("권한 그룹 멤버 일괄 업데이트 성공", {
      masterObjid,
      added: toAdd.length,
      removed: toRemove.length,
    });

    const response: ApiResponse<null> = {
      success: true,
      message: "권한 그룹 멤버가 업데이트되었습니다",
      data: null,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("권한 그룹 멤버 업데이트 실패", { error });
    res.status(500).json({
      success: false,
      message: "권한 그룹 멤버 업데이트 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 권한 그룹 멤버 제거
 */
export const removeRoleMembers = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const masterObjid = parseInt(req.params.id, 10);
    const { userIds } = req.body;

    if (isNaN(masterObjid)) {
      res.status(400).json({
        success: false,
        message: "유효하지 않은 권한 그룹 ID입니다",
      });
      return;
    }

    if (!Array.isArray(userIds) || userIds.length === 0) {
      res.status(400).json({
        success: false,
        message: "제거할 사용자 ID 목록이 필요합니다",
      });
      return;
    }

    // 기존 권한 그룹 조회
    const roleGroup = await RoleService.getRoleGroupById(masterObjid);
    if (!roleGroup) {
      res.status(404).json({
        success: false,
        message: "권한 그룹을 찾을 수 없습니다",
      });
      return;
    }

    // 권한 체크
    if (
      !isSuperAdmin(req.user) &&
      !canAccessCompanyData(req.user, roleGroup.companyCode)
    ) {
      res.status(403).json({
        success: false,
        message: "권한 그룹 멤버 제거 권한이 없습니다",
      });
      return;
    }

    await RoleService.removeRoleMembers(
      masterObjid,
      userIds,
      req.user?.userId || "SYSTEM"
    );

    const response: ApiResponse<null> = {
      success: true,
      message: "권한 그룹 멤버 제거 성공",
      data: null,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("권한 그룹 멤버 제거 실패", { error });
    res.status(500).json({
      success: false,
      message: "권한 그룹 멤버 제거 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 메뉴 권한 목록 조회
 */
export const getMenuPermissions = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const authObjid = parseInt(req.params.id, 10);

    if (isNaN(authObjid)) {
      res.status(400).json({
        success: false,
        message: "유효하지 않은 권한 그룹 ID입니다",
      });
      return;
    }

    // 기존 권한 그룹 조회
    const roleGroup = await RoleService.getRoleGroupById(authObjid);
    if (!roleGroup) {
      res.status(404).json({
        success: false,
        message: "권한 그룹을 찾을 수 없습니다",
      });
      return;
    }

    // 권한 체크
    if (
      !isSuperAdmin(req.user) &&
      !canAccessCompanyData(req.user, roleGroup.companyCode)
    ) {
      res.status(403).json({
        success: false,
        message: "메뉴 권한 조회 권한이 없습니다",
      });
      return;
    }

    const permissions = await RoleService.getMenuPermissions(authObjid);

    const response: ApiResponse<any[]> = {
      success: true,
      message: "메뉴 권한 조회 성공",
      data: permissions,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("메뉴 권한 조회 실패", { error });
    res.status(500).json({
      success: false,
      message: "메뉴 권한 조회 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 메뉴 권한 설정
 */
export const setMenuPermissions = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const authObjid = parseInt(req.params.id, 10);
    const { permissions } = req.body;

    if (isNaN(authObjid)) {
      res.status(400).json({
        success: false,
        message: "유효하지 않은 권한 그룹 ID입니다",
      });
      return;
    }

    if (!Array.isArray(permissions)) {
      res.status(400).json({
        success: false,
        message: "권한 목록이 필요합니다",
      });
      return;
    }

    // 기존 권한 그룹 조회
    const roleGroup = await RoleService.getRoleGroupById(authObjid);
    if (!roleGroup) {
      res.status(404).json({
        success: false,
        message: "권한 그룹을 찾을 수 없습니다",
      });
      return;
    }

    // 권한 체크
    if (
      !isSuperAdmin(req.user) &&
      !canAccessCompanyData(req.user, roleGroup.companyCode)
    ) {
      res.status(403).json({
        success: false,
        message: "메뉴 권한 설정 권한이 없습니다",
      });
      return;
    }

    await RoleService.setMenuPermissions(
      authObjid,
      permissions,
      req.user?.userId || "SYSTEM"
    );

    const response: ApiResponse<null> = {
      success: true,
      message: "메뉴 권한 설정 성공",
      data: null,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("메뉴 권한 설정 실패", { error });
    res.status(500).json({
      success: false,
      message: "메뉴 권한 설정 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 사용자가 속한 권한 그룹 목록 조회
 */
export const getUserRoleGroups = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const userId = req.params.userId || req.user?.userId;
    const companyCode = req.user?.companyCode;

    if (!userId || !companyCode) {
      res.status(400).json({
        success: false,
        message: "사용자 ID 또는 회사 코드가 필요합니다",
      });
      return;
    }

    const roleGroups = await RoleService.getUserRoleGroups(userId, companyCode);

    const response: ApiResponse<any[]> = {
      success: true,
      message: "사용자 권한 그룹 조회 성공",
      data: roleGroups,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("사용자 권한 그룹 조회 실패", { error });
    res.status(500).json({
      success: false,
      message: "사용자 권한 그룹 조회 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 전체 메뉴 목록 조회 (권한 설정용)
 */
export const getAllMenus = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const requestedCompanyCode = req.query.companyCode as string | undefined;

    logger.info("🔍 [getAllMenus] API 호출", {
      userId: req.user?.userId,
      userType: req.user?.userType,
      userCompanyCode: req.user?.companyCode,
      requestedCompanyCode,
    });

    // 권한 체크
    if (!isSuperAdmin(req.user) && !isCompanyAdmin(req.user)) {
      logger.warn("❌ [getAllMenus] 권한 없음", {
        userId: req.user?.userId,
        userType: req.user?.userType,
      });
      res.status(403).json({
        success: false,
        message: "관리자 권한이 필요합니다",
      });
      return;
    }

    // 회사 코드 결정: 최고 관리자는 요청한 코드 사용, 회사 관리자는 자기 회사만
    let companyCode: string | undefined;
    if (isSuperAdmin(req.user)) {
      // 최고 관리자: 요청한 회사 코드 사용 (없으면 전체)
      companyCode = requestedCompanyCode;
      logger.info("✅ [getAllMenus] 최고 관리자 - 요청된 회사 코드 사용", {
        companyCode: companyCode || "전체",
      });
    } else {
      // 회사 관리자: 자기 회사 코드만 사용
      companyCode = req.user?.companyCode;
      logger.info("✅ [getAllMenus] 회사 관리자 - 자기 회사 코드 적용", {
        companyCode,
      });
    }

    logger.info("✅ [getAllMenus] 관리자 권한 확인 완료", {
      isSuperAdmin: isSuperAdmin(req.user),
      isCompanyAdmin: isCompanyAdmin(req.user),
      finalCompanyCode: companyCode || "전체",
    });

    const menus = await RoleService.getAllMenus(companyCode);

    logger.info("✅ [getAllMenus] API 응답 준비", {
      menuCount: menus.length,
      companyCode: companyCode || "전체",
    });

    const response: ApiResponse<any[]> = {
      success: true,
      message: "메뉴 목록 조회 성공",
      data: menus,
    };

    res.status(200).json(response);
  } catch (error) {
    logger.error("❌ [getAllMenus] 메뉴 목록 조회 실패", { error });
    res.status(500).json({
      success: false,
      message: "메뉴 목록 조회 중 오류가 발생했습니다",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};
