// 인증 컨트롤러
// 기존 Java ApiLoginController를 Node.js로 포팅

import { Request, Response } from "express";
import { AuthService } from "../services/authService";
import { JwtUtils } from "../utils/jwtUtils";
import { LoginRequest, UserInfo, ApiResponse, PersonBean } from "../types/auth";
import { logger } from "../utils/logger";
import { sendSmartFactoryLog } from "../utils/smartFactoryLog";

export class AuthController {
  /**
   * POST /api/auth/login
   * 기존 Java ApiLoginController.login() 메서드 포팅
   */
  static async login(req: Request, res: Response): Promise<void> {
    try {
      const { userId, password }: LoginRequest = req.body;
      const remoteAddr = req.ip || req.connection.remoteAddress || "unknown";

      logger.debug(`로그인 요청: ${userId}`);

      // 입력값 검증
      if (!userId || !password) {
        res.status(400).json({
          success: false,
          message: "사용자 ID와 비밀번호를 입력해주세요.",
          error: {
            code: "INVALID_INPUT",
            details: "필수 입력값이 누락되었습니다.",
          },
        });
        return;
      }

      // 로그인 프로세스 실행
      const loginResult = await AuthService.processLogin(
        userId,
        password,
        remoteAddr
      );

      if (loginResult.success && loginResult.userInfo && loginResult.token) {
        // 로그인 성공
        const userInfo: UserInfo = {
          userId: loginResult.userInfo.userId,
          userName: loginResult.userInfo.userName || "",
          deptName: loginResult.userInfo.deptName || "",
          companyCode: loginResult.userInfo.companyCode || "ILSHIN",
        };

        logger.debug(`로그인 사용자 정보: ${userInfo.userId} (${userInfo.companyCode})`);

        // 메뉴 조회를 위한 공통 파라미터
        const { AdminService } = await import("../services/adminService");
        const paramMap = {
          userId: loginResult.userInfo.userId,
          userCompanyCode: loginResult.userInfo.companyCode || "ILSHIN",
          userType: loginResult.userInfo.userType,
          userLang: "ko",
        };

        // 사용자의 첫 번째 접근 가능한 메뉴 조회
        let firstMenuPath: string | null = null;
        try {
          const menuList = await AdminService.getUserMenuList(paramMap);
          logger.debug(`로그인 후 메뉴 조회: 총 ${menuList.length}개 메뉴`);

          const firstMenu = menuList.find((menu: any) => {
            const level = menu.lev || menu.level;
            const url = menu.menu_url || menu.url;
            return level >= 2 && url && url.trim() !== "" && url !== "#";
          });

          if (firstMenu) {
            firstMenuPath = firstMenu.menu_url || firstMenu.url;
            logger.debug(`첫 번째 메뉴: ${firstMenuPath}`);
          } else {
            logger.debug("접근 가능한 메뉴 없음, 메인 페이지로 이동");
          }
        } catch (menuError) {
          logger.warn("메뉴 조회 중 오류 발생 (무시하고 계속):", menuError);
        }

        // 스마트공장 활용 로그 전송 (비동기, 응답 블로킹 안 함)
        sendSmartFactoryLog({
          userId: userInfo.userId,
          remoteAddr,
          useType: "접속",
        }).catch(() => {});

        // POP 랜딩 경로 조회
        let popLandingPath: string | null = null;
        try {
          const popResult = await AdminService.getPopMenuList(paramMap);
          if (popResult.landingMenu?.menu_url) {
            popLandingPath = popResult.landingMenu.menu_url;
          } else if (popResult.childMenus.length === 1) {
            popLandingPath = popResult.childMenus[0].menu_url;
          } else if (popResult.childMenus.length > 1) {
            popLandingPath = "/pop";
          }
          logger.debug(`POP 랜딩 경로: ${popLandingPath}`);
        } catch (popError) {
          logger.warn("POP 메뉴 조회 중 오류 (무시):", popError);
        }

        res.status(200).json({
          success: true,
          message: "로그인 성공",
          data: {
            userInfo,
            token: loginResult.token,
            firstMenuPath,
            popLandingPath,
          },
        });
      } else {
        // 로그인 실패
        res.status(401).json({
          success: false,
          message: "로그인 실패",
          error: {
            code: "LOGIN_FAILED",
            details:
              loginResult.errorReason || "알 수 없는 오류가 발생했습니다.",
          },
        });
      }
    } catch (error) {
      logger.error(
        `로그인 API 오류: ${error instanceof Error ? error.message : error}`
      );
      res.status(500).json({
        success: false,
        message: "서버 오류가 발생했습니다.",
        error: {
          code: "SERVER_ERROR",
          details:
            error instanceof Error
              ? error.message
              : "알 수 없는 오류가 발생했습니다.",
        },
      });
    }
  }

  /**
   * POST /api/auth/switch-company
   * WACE 관리자 전용: 다른 회사로 전환
   */
  static async switchCompany(req: Request, res: Response): Promise<void> {
    try {
      const { companyCode } = req.body;
      const authHeader = req.get("Authorization");
      const token = authHeader && authHeader.split(" ")[1];

      if (!token) {
        res.status(401).json({
          success: false,
          message: "인증 토큰이 필요합니다.",
          error: { code: "TOKEN_MISSING" },
        });
        return;
      }

      // 현재 사용자 정보 확인
      const currentUser = JwtUtils.verifyToken(token);
      
      // WACE 관리자 권한 체크 (userType = "SUPER_ADMIN"만 확인)
      // 이미 다른 회사로 전환한 상태(companyCode != "*")에서도 다시 전환 가능해야 함
      if (currentUser.userType !== "SUPER_ADMIN") {
        logger.warn(`회사 전환 권한 없음: userId=${currentUser.userId}, userType=${currentUser.userType}, companyCode=${currentUser.companyCode}`);
        res.status(403).json({
          success: false,
          message: "회사 전환은 최고 관리자(SUPER_ADMIN)만 가능합니다.",
          error: { code: "FORBIDDEN" },
        });
        return;
      }

      // 전환할 회사 코드 검증
      if (!companyCode || companyCode.trim() === "") {
        res.status(400).json({
          success: false,
          message: "전환할 회사 코드가 필요합니다.",
          error: { code: "INVALID_INPUT" },
        });
        return;
      }

      logger.info(`=== WACE 관리자 회사 전환 ===`, {
        userId: currentUser.userId,
        originalCompanyCode: currentUser.companyCode,
        targetCompanyCode: companyCode,
      });

      // 회사 코드 존재 여부 확인 (company_code가 "*"가 아닌 경우만)
      if (companyCode !== "*") {
        const { query } = await import("../database/db");
        const companies = await query<any>(
          "SELECT company_code, company_name FROM company_mng WHERE company_code = $1",
          [companyCode]
        );

        if (companies.length === 0) {
          res.status(404).json({
            success: false,
            message: "존재하지 않는 회사 코드입니다.",
            error: { code: "COMPANY_NOT_FOUND" },
          });
          return;
        }
      }

      // 새로운 JWT 토큰 발급 (company_code만 변경)
      const newPersonBean: PersonBean = {
        ...currentUser,
        companyCode: companyCode.trim(), // 전환할 회사 코드로 변경
      };

      const newToken = JwtUtils.generateToken(newPersonBean);

      logger.info(`✅ 회사 전환 성공: ${currentUser.userId} → ${companyCode}`);

      res.status(200).json({
        success: true,
        message: "회사 전환 완료",
        data: {
          token: newToken,
          companyCode: companyCode.trim(),
        },
      });
    } catch (error) {
      logger.error(
        `회사 전환 API 오류: ${error instanceof Error ? error.message : error}`
      );
      res.status(500).json({
        success: false,
        message: "회사 전환 중 오류가 발생했습니다.",
        error: {
          code: "SERVER_ERROR",
          details:
            error instanceof Error
              ? error.message
              : "알 수 없는 오류가 발생했습니다.",
        },
      });
    }
  }

  /**
   * POST /api/auth/logout
   * 기존 Java ApiLoginController.logout() 메서드 포팅
   */
  static async logout(req: Request, res: Response): Promise<void> {
    try {
      const remoteAddr = req.ip || req.connection.remoteAddress || "unknown";

      // JWT 토큰에서 사용자 정보 추출
      const authHeader = req.get("Authorization");
      const token = authHeader && authHeader.split(" ")[1];

      if (token) {
        try {
          const userInfo = JwtUtils.verifyToken(token);
          await AuthService.processLogout(userInfo.userId, remoteAddr);
        } catch (tokenError) {
          logger.warn(
            `로그아웃 시 토큰 검증 실패: ${tokenError instanceof Error ? tokenError.message : tokenError}`
          );
        }
      }

      res.status(200).json({
        success: true,
        message: "로그아웃되었습니다.",
        data: null,
      });
    } catch (error) {
      logger.error(
        `로그아웃 API 오류: ${error instanceof Error ? error.message : error}`
      );
      res.status(500).json({
        success: false,
        message: "로그아웃 처리 중 오류가 발생했습니다.",
        error: {
          code: "LOGOUT_ERROR",
          details:
            error instanceof Error
              ? error.message
              : "알 수 없는 오류가 발생했습니다.",
        },
      });
    }
  }

  /**
   * GET /api/auth/me
   * 기존 Java ApiLoginController.getCurrentUser() 메서드 포팅
   */
  static async getCurrentUser(req: Request, res: Response): Promise<void> {
    try {
      const authHeader = req.get("Authorization");
      const token = authHeader && authHeader.split(" ")[1];

      if (!token) {
        res.status(401).json({
          success: false,
          message: "인증되지 않은 사용자입니다.",
          error: {
            code: "NOT_AUTHENTICATED",
            details: "세션이 만료되었거나 로그인이 필요합니다.",
          },
        });
        return;
      }

      const userInfo = JwtUtils.verifyToken(token);

      // DB에서 최신 사용자 정보 조회 (locale 포함)
      const dbUserInfo = await AuthService.getUserInfo(userInfo.userId);

      if (!dbUserInfo) {
        res.status(401).json({
          success: false,
          message: "사용자 정보를 찾을 수 없습니다.",
          error: {
            code: "USER_NOT_FOUND",
            details: "사용자 정보가 삭제되었거나 존재하지 않습니다.",
          },
        });
        return;
      }

      // 프론트엔드 호환성을 위해 더 많은 사용자 정보 반환
      // ⚠️ JWT 토큰의 companyCode를 우선 사용 (회사 전환 기능 지원)
      const userInfoResponse: any = {
        userId: dbUserInfo.userId,
        userName: dbUserInfo.userName || "",
        deptName: dbUserInfo.deptName || "",
        companyCode: userInfo.companyCode || dbUserInfo.companyCode || "ILSHIN", // JWT 토큰 우선
        company_code: userInfo.companyCode || dbUserInfo.companyCode || "ILSHIN", // JWT 토큰 우선
        userType: userInfo.userType || dbUserInfo.userType || "USER", // JWT 토큰 우선
        userTypeName: dbUserInfo.userTypeName || "일반사용자",
        email: dbUserInfo.email || "",
        photo: dbUserInfo.photo,
        locale: dbUserInfo.locale || "KR", // locale 정보 추가
        deptCode: dbUserInfo.deptCode, // 추가 필드
        isAdmin:
          dbUserInfo.userType === "ADMIN" || dbUserInfo.userId === "plm_admin",
      };

      res.status(200).json({
        success: true,
        message: "사용자 정보 조회 성공",
        data: userInfoResponse,
      });
    } catch (error) {
      logger.error(
        `사용자 정보 조회 API 오류: ${error instanceof Error ? error.message : error}`
      );
      res.status(401).json({
        success: false,
        message: "인증되지 않은 사용자입니다.",
        error: {
          code: "NOT_AUTHENTICATED",
          details: "세션이 만료되었거나 로그인이 필요합니다.",
        },
      });
    }
  }

  /**
   * GET /api/auth/status
   * 기존 Java ApiLoginController.checkAuthStatus() 메서드 포팅
   */
  static async checkAuthStatus(req: Request, res: Response): Promise<void> {
    try {
      const authHeader = req.get("Authorization");
      const token = authHeader && authHeader.split(" ")[1];

      if (!token) {
        res.status(200).json({
          success: true,
          message: "세션 상태 확인",
          data: {
            isLoggedIn: false,
            isAdmin: false,
          },
        });
        return;
      }

      const validation = JwtUtils.validateToken(token);

      if (!validation.isValid) {
        res.status(200).json({
          success: true,
          message: "세션 상태 확인",
          data: {
            isLoggedIn: false,
            isAdmin: false,
            error: validation.error,
          },
        });
        return;
      }

      // 토큰에서 사용자 정보 추출하여 관리자 권한 확인
      let isAdmin = false;
      try {
        const userInfo = JwtUtils.verifyToken(token);
        // 기존 Java 로직과 동일: plm_admin 사용자만 관리자로 인식
        isAdmin =
          userInfo.userId === "plm_admin" || userInfo.userType === "ADMIN";

        logger.info(`인증 상태 확인: ${userInfo.userId}, 관리자: ${isAdmin}`);
      } catch (error) {
        logger.error(`토큰에서 사용자 정보 추출 실패: ${error}`);
      }

      res.status(200).json({
        success: true,
        message: "세션 상태 확인",
        data: {
          isLoggedIn: true,
          isAdmin: isAdmin,
        },
      });
    } catch (error) {
      logger.error(
        `세션 상태 확인 API 오류: ${error instanceof Error ? error.message : error}`
      );
      res.status(500).json({
        success: false,
        message: "세션 상태 확인 중 오류가 발생했습니다.",
        error: {
          code: "SESSION_CHECK_ERROR",
          details:
            error instanceof Error
              ? error.message
              : "알 수 없는 오류가 발생했습니다.",
        },
      });
    }
  }

  /**
   * POST /api/auth/refresh
   * JWT 토큰 갱신 API
   */
  static async refreshToken(req: Request, res: Response): Promise<void> {
    try {
      const authHeader = req.get("Authorization");
      const token = authHeader && authHeader.split(" ")[1];

      if (!token) {
        res.status(401).json({
          success: false,
          message: "토큰이 필요합니다.",
          error: {
            code: "TOKEN_MISSING",
            details: "인증 토큰이 필요합니다.",
          },
        });
        return;
      }

      const newToken = JwtUtils.refreshToken(token);

      res.status(200).json({
        success: true,
        message: "토큰 갱신 성공",
        data: {
          token: newToken,
        },
      });
    } catch (error) {
      logger.error(
        `토큰 갱신 API 오류: ${error instanceof Error ? error.message : error}`
      );
      res.status(401).json({
        success: false,
        message: "토큰 갱신에 실패했습니다.",
        error: {
          code: "TOKEN_REFRESH_ERROR",
          details:
            error instanceof Error
              ? error.message
              : "알 수 없는 오류가 발생했습니다.",
        },
      });
    }
  }

  /**
   * POST /api/auth/signup
   * 공차중계 회원가입 API
   */
  static async signup(req: Request, res: Response): Promise<void> {
    try {
      const { userId, password, userName, phoneNumber, licenseNumber, vehicleNumber, vehicleType } = req.body;

      logger.info(`=== 공차중계 회원가입 API 호출 ===`);
      logger.info(`userId: ${userId}, vehicleNumber: ${vehicleNumber}`);

      // 입력값 검증
      if (!userId || !password || !userName || !phoneNumber || !licenseNumber || !vehicleNumber) {
        res.status(400).json({
          success: false,
          message: "필수 입력값이 누락되었습니다.",
          error: {
            code: "INVALID_INPUT",
            details: "아이디, 비밀번호, 이름, 연락처, 면허번호, 차량번호는 필수입니다.",
          },
        });
        return;
      }

      // 회원가입 처리
      const signupResult = await AuthService.signupDriver({
        userId,
        password,
        userName,
        phoneNumber,
        licenseNumber,
        vehicleNumber,
        vehicleType,
      });

      if (signupResult.success) {
        logger.info(`공차중계 회원가입 성공: ${userId}`);
        res.status(201).json({
          success: true,
          message: "회원가입이 완료되었습니다.",
        });
      } else {
        logger.warn(`공차중계 회원가입 실패: ${userId} - ${signupResult.message}`);
        res.status(400).json({
          success: false,
          message: signupResult.message || "회원가입에 실패했습니다.",
          error: {
            code: "SIGNUP_FAILED",
            details: signupResult.message,
          },
        });
      }
    } catch (error) {
      logger.error("공차중계 회원가입 API 오류:", error);
      res.status(500).json({
        success: false,
        message: "회원가입 처리 중 오류가 발생했습니다.",
        error: {
          code: "SIGNUP_ERROR",
          details: error instanceof Error ? error.message : "알 수 없는 오류",
        },
      });
    }
  }
}
