const userService = require('../services/userService');
const ApiResponse = require('../utils/apiResponse');
const { asyncHandler } = require('../middleware/errorHandler');
const { User } = require('../models');
const { generateUniqueUsernameRandom } = require('../utils/helpers');
const { UnauthorizedError } = require('../utils/errors');

const setAuthCookies = (res, accessToken, refreshToken) => {
  res.cookie("accessToken", accessToken, {
    httpOnly: true,
    secure: process.env.NODE_ENV === "production",
    sameSite: "strict",
    maxAge: 15 * 60 * 1000, // match config.jwt.expire
  });

  res.cookie("refreshToken", refreshToken, {
    httpOnly: true,
    secure: process.env.NODE_ENV === "production",
    sameSite: "strict",
    maxAge: 7 * 24 * 60 * 60 * 1000, // match config.jwt.refreshExpire
    path: "/auth/refresh-token", // ✅ cookie only sent on this route
  });
};

exports.register = asyncHandler(async (req, res) => {

  const { email, pin, confirm_pin, firstName, lastName, referralCode } = req.body;

  const ip = req.ip || req.connection.remoteAddress;
  const device = req.headers['user-agent'];
  const username = generateUniqueUsernameRandom(email)

  const result = await userService.register(
    { email, pin, confirm_pin, username, firstName, lastName, referralCode },
    ip,
    device
  );

  ApiResponse.created(res, {
    user: result.user,
    message: 'Registration successful. Please check your email to verify your account.',
  });
});


exports.registerNew = asyncHandler(async (req, res) => {

  const { firstName, lastName, email, phone, country, currency, password, confirmPassword, pin, confirmPin, referralCode } = req.body;

  const ip = req.ip || req.connection.remoteAddress;
  const device = req.headers['user-agent'];
  const username = generateUniqueUsernameRandom(email)

  const result = await userService.registerNew(
    { firstName, lastName, email, username, phone, country, currency, password, confirmPassword, pin, confirmPin, referralCode },
    ip,
    device
  );

  ApiResponse.created(res, {
    //user: result.user,
    result: result,
    message: 'Registration successful. Please check your email to verify your account.',
  });
});

exports.start = asyncHandler(async (req, res) => {
  const { email } = req.body;
  const ip = req.ip || req.connection.remoteAddress;
  const device = req.headers['user-agent'];

  const result = await userService.start(
    { email },
    ip,
    device
  );

  ApiResponse.created(res, {
    registered: result.registered,
    loginW: result.loginW,
    message: result.registered ? 'User Exists' : 'User Does Not Exist'
  });
})


exports.verifyOTP = asyncHandler(async (req, res) => {
  const { email, code } = req.body;

  console.log('Verify OTP Request:', req.body);

  const result = await userService.verifyOTP({ email, code });

  ApiResponse.success(res, {
    validate: result.status,
    message: result.registered ? 'User Exists' : 'User Does Not Exist',
  });
});

exports.login = asyncHandler(async (req, res) => {
  const { email, password, twoFactorCode } = req.body;
  const ip = req.ip || req.connection.remoteAddress;
  const device = req.headers['user-agent'];

  const result = await userService.login(email, password, ip, device, twoFactorCode);

  if (result.requires2FA) {
    return ApiResponse.success(res, { requires2FA: true, message: 'Please enter your 2FA code' });
  }
  setAuthCookies(res, result.accessToken, result.refreshToken);

  ApiResponse.success(res, {
    user: result.user,
  }, 'Login successful');
});

exports.loginWithPin = asyncHandler(async (req, res) => {
  const { email, pin, twoFactorCode } = req.body;
  const ip = req.ip || req.connection.remoteAddress;
  const device = req.headers['user-agent'];

  const result = await userService.loginWithPin(email, pin, ip, device, twoFactorCode);

  if (result.requires2FA) {
    return ApiResponse.success(res, { requires2FA: true, message: 'Please enter your 2FA code', type: result.type });
  }

  setAuthCookies(res, result.accessToken, result.refreshToken);

  ApiResponse.success(res, {
    user: result.user,
  }, 'Login successful');
});

exports.verify2fa = asyncHandler(async (req, res) => {
  const { email, code } = req.body;
  const ip = req.ip || req.connection.remoteAddress;
  const device = req.headers['user-agent'];
  console.log('Verify 2FA Request:', req.body);
  const result = await userService.verify2fa(email, code, ip, device);
  setAuthCookies(res, result.accessToken, result.refreshToken);
  ApiResponse.success(res, {
    user: result.user,
  }, 'Login successful');
});

exports.logout = asyncHandler(async (req, res) => {
  await userService.logout(req.sessionId);
  res.clearCookie("accessToken");
  res.clearCookie("refreshToken", { path: "/auth/refresh-token" }); // ✅ match the path

  ApiResponse.success(res, null, 'Logout successful');
});

exports.logoutAll = asyncHandler(async (req, res) => {
  await userService.logoutAll(req.user.id);
  ApiResponse.success(res, null, 'Logged out from all devices');
});

exports.refreshToken = asyncHandler(async (req, res) => {
  const refreshToken = req?.cookies?.refreshToken;

  if (!refreshToken) {
    throw new UnauthorizedError('No refresh token');
  }

  const result = await userService.refreshToken(refreshToken);
  setAuthCookies(res, result.accessToken, result.refreshToken);

  // ✅ Don't send result — tokens stay in cookies only
  ApiResponse.success(res, null, 'Token refreshed');
});

exports.verifyEmail = asyncHandler(async (req, res) => {
  const { token } = req.body;
  await userService.verifyEmail(token);
  ApiResponse.success(res, null, 'Email verified successfully');
});

exports.resendVerification = asyncHandler(async (req, res) => {
  const { email } = req.body;
  await userService.resendVerification(email);
  ApiResponse.success(res, null, 'Verification email sent');
});

exports.resend2fa = asyncHandler(async (req, res) => {
  const { email } = req.body;
  const ip = req.ip || req.connection.remoteAddress;
  const device = req.headers['user-agent'];
  await userService.resend2fa(email, ip, device);
  ApiResponse.success(res, null, 'Two factor email sent');
});

exports.validateToken = asyncHandler(async (req, res) => {
  const { token } = req.query;
  await userService.validateToken(token);
  ApiResponse.success(res, null, 'validated');
});

exports.validatePinToken = asyncHandler(async (req, res) => {
  const { token } = req.query;
  await userService.validatePinToken(token);
  ApiResponse.success(res, null, 'validated');
});

exports.forgotPassword = asyncHandler(async (req, res) => {
  const { email } = req.body;
  await userService.forgotPassword(email);
  ApiResponse.success(res, null, 'If an account exists, a reset email will be sent');
});

exports.resetPassword = asyncHandler(async (req, res) => {
  const { token, password } = req.body;
  await userService.resetPassword(token, password);
  ApiResponse.success(res, null, 'Password reset successful');
});

exports.forgotPin = asyncHandler(async (req, res) => {
  const { email } = req.body;
  await userService.forgotPin(email);
  ApiResponse.success(res, null, 'If an account exists, a reset email will be sent');
});

exports.resetPin = asyncHandler(async (req, res) => {
  const { token, pin } = req.body;
  await userService.resetPin(token, pin);
  ApiResponse.success(res, null, 'Pin reset successful');
});

exports.changePassword = asyncHandler(async (req, res) => {
  const { currentPassword, password } = req.body;
  await userService.changePassword(req.user.id, currentPassword, password);
  ApiResponse.success(res, null, 'Password changed successfully');
});

exports.getMe = asyncHandler(async (req, res) => {
  const user = await userService.getById(req.user.id);
  ApiResponse.success(res, { user });
});

exports.setup2FA = asyncHandler(async (req, res) => {
  const result = await userService.setup2FA(req.user.id);
  ApiResponse.success(res, result, '2FA setup initiated');
});

exports.enable2FA = asyncHandler(async (req, res) => {
  const { code } = req.body;
  const result = await userService.enable2FA(req.user.id, code);
  ApiResponse.success(res, result, '2FA enabled successfully');
});

exports.disable2FA = asyncHandler(async (req, res) => {
  const { code } = req.body;
  await userService.disable2FA(req.user.id, code);
  ApiResponse.success(res, null, '2FA disabled successfully');
});

exports.verify2FA = asyncHandler(async (req, res) => {
  const { code } = req.body;
  const isValid = await userService.verify2FACode(req.user.id, code);
  if (!isValid) {
    return ApiResponse.error(res, 'Invalid 2FA code', 400);
  }
  ApiResponse.success(res, { verified: true }, '2FA verified');
});

exports.getBackupCodes = asyncHandler(async (req, res) => {
  const user = await userService.getById(req.user.id);
  ApiResponse.success(res, { backupCodes: user.backupCodes || [] });
});

exports.regenerateBackupCodes = asyncHandler(async (req, res) => {
  ApiResponse.success(res, null, 'Backup codes regenerated');
});
