const {
  getUserByUserEmailDb,
  createUserDb,
  getUserByUsernameDb
} = require('../db/user.db');
const { hashPassword, comparePassword } = require('../helpers/hashPassword');
const { ErrorHandler } = require('../helpers/error');
const JWTService = require('../utils/jwt');

class AuthService {
  // Register
  static async register(data) {
    try {
      const existingEmail = await getUserByUserEmailDb(data.user_email);
      const existingUsername = await getUserByUsernameDb(data.user_name);

      if (existingUsername) {
        throw new ErrorHandler(400, 'Username is already taken');
      }
      if (existingEmail) {
        throw new ErrorHandler(400, 'Email is already taken');
      }

      const hashedPassword = await hashPassword(data.user_password);

      const userId = await createUserDb({
        user_fullname: data.user_fullname,
        user_name: data.user_name,
        user_email: data.user_email,
        user_phone: data.user_phone,
        user_password: hashedPassword,
        is_sa: 0,
        is_active: 1,
        is_approve: 1,
      });

      const newUser = {
        user_id: userId,
        user_fullname: data.user_fullname,
        user_name: data.user_name,
        user_email: data.user_email,
        user_phone: data.user_phone
      };

      return { user: newUser };
    } catch (error) {
      throw new ErrorHandler(error.statusCode, error.message);
    }
  }

  // Login
  static async login(data) {
    try {
      const { identifier, password, captcha, captchaText } = data;

      if (!captcha || captcha.toLowerCase() !== captchaText.toLowerCase()) {
        throw new ErrorHandler(400, 'Invalid captcha');
      }

      let user;
      if (identifier.includes('@')) {
        user = await getUserByUserEmailDb(identifier);
      } else {
        user = await getUserByUsernameDb(identifier);
      }

      if (!user) throw new ErrorHandler(401, 'Invalid credentials');

      const passwordMatch = await comparePassword(password, user.user_password);
      if (!passwordMatch) throw new ErrorHandler(401, 'Invalid credentials');

      if (!user.is_active) throw new ErrorHandler(403, 'User is inactive');
      if (!user.is_approve) throw new ErrorHandler(403, 'Your account has not been approved by admin yet.');

      const payload = {
        user_id: user.user_id,
        user_fullname: user.user_fullname,
        user_name: user.user_name,
        user_email: user.user_email,
        user_phone: user.user_phone,
        role_id: user.role_id,
        role_name: user.role_name,
        is_sa: user.is_sa
      };

      const tokens = JWTService.generateTokenPair(payload);
      return { user: payload, tokens };
    } catch (error) {
      throw new ErrorHandler(error.statusCode, error.message);
    }
  }

  // Refresh Token
  static async refreshToken(refreshToken) {
    try {
      let decoded;
      try {
        decoded = JWTService.verifyRefreshToken(refreshToken);
      } catch (err) {
        if (err.message.includes('expired')) {
          throw new ErrorHandler(401, 'Refresh token expired');
        }
        throw new ErrorHandler(401, 'Invalid refresh token');
      }

      const payload = {
        user_id: decoded.user_id,
        user_fullname: decoded.user_fullname,
        user_name: decoded.user_name,
        user_email: decoded.user_email,
        user_phone: decoded.user_phone,
        role_id: decoded.role_id,
        role_name: decoded.role_name,
        is_sa: decoded.is_sa
      };

      const accessToken = JWTService.generateAccessToken(payload);

      return {
        accessToken,
        tokenType: 'Bearer',
        expiresIn: 900
      };
    } catch (error) {
      throw new ErrorHandler(error.statusCode, error.message);
    }
  }
}

module.exports = AuthService;
