/**
 * Authentication Controllers
 * Request handlers for authentication endpoints
 */

// Import authentication service
const authService = require('../services');
// Import user service for setup
const userService = require('../../users/services');
// Import async handler wrapper
const asyncHandler = require('../../../middlewares/asyncHandler');
// Import logger for logging
const logger = require('../../../utils/logger');
// Import SystemLog model for audit trail
const { SystemLog, User } = require('../../../models');

/**
 * Login controller
 * Handles user login with username and password
 * POST /api/auth/login
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const login = asyncHandler(async (req, res) => {
  // Extract username and password from request body
  const { username, password } = req.body;
  
  // Call authentication service to login user
  const result = await authService.login(username, password);
  
  // Log successful login to system logs
  await SystemLog.create({
    user_id: result.user.id, // User ID
    action: 'LOGIN', // Action type
    entity: 'User', // Entity type
    entity_id: result.user.id, // Entity ID
    payload: { username: result.user.username, method: 'password' }, // Log payload
  });
  
  // Log login action
  logger.info(`User logged in: ${result.user.username}`, {
    userId: result.user.id,
    role: result.user.role,
  });
  
  // Return success response with user data and token
  return res.status(200).json({
    success: true, // Indicate success
    message: 'Login successful', // Success message
    data: result, // User data and token
  });
});

/**
 * PIN login controller
 * Handles quick POS login with username and PIN code
 * POST /api/auth/login-pin
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const loginWithPin = asyncHandler(async (req, res) => {
  // Extract username and PIN code from request body
  const { username, pin_code } = req.body;
  
  // Call authentication service to login user with PIN
  const result = await authService.loginWithPin(username, pin_code);
  
  // Log successful PIN login to system logs
  await SystemLog.create({
    user_id: result.user.id, // User ID
    action: 'LOGIN_PIN', // Action type
    entity: 'User', // Entity type
    entity_id: result.user.id, // Entity ID
    payload: { username: result.user.username, method: 'pin' }, // Log payload
  });
  
  // Log PIN login action
  logger.info(`User logged in with PIN: ${result.user.username}`, {
    userId: result.user.id,
    role: result.user.role,
  });
  
  // Return success response with user data and token
  return res.status(200).json({
    success: true, // Indicate success
    message: 'PIN login successful', // Success message
    data: result, // User data and token
  });
});

/**
 * Get current user profile controller
 * Returns the authenticated user's profile
 * GET /api/auth/profile
 * @param {Object} req - Express request object (must have req.user from auth middleware)
 * @param {Object} res - Express response object
 */
const getProfile = asyncHandler(async (req, res) => {
  // Get user ID from authenticated request (set by auth middleware)
  const userId = req.user.id;
  
  // Call authentication service to get user by ID
  const user = await authService.getUserById(userId);
  
  // Return success response with user profile
  return res.status(200).json({
    success: true, // Indicate success
    message: 'Profile retrieved successfully', // Success message
    data: { user }, // User profile data
  });
});

/**
 * Setup/Initialize system controller
 * Creates the first admin user when database is empty
 * POST /api/auth/setup
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const setup = asyncHandler(async (req, res) => {
  // Check if any users already exist
  const userCount = await User.count();
  
  // If users exist, deny setup (system already initialized)
  if (userCount > 0) {
    return res.status(403).json({
      success: false, // Indicate failure
      message: 'System already initialized. Please login to create additional users.', // Error message
    });
  }
  
  // Extract admin user data from request body
  const { username, email, password, full_name, pin_code } = req.body;
  
  // Validate required fields
  if (!username || !email || !password || !full_name) {
    return res.status(400).json({
      success: false, // Indicate failure
      message: 'Username, email, password, and full_name are required', // Error message
    });
  }
  
  // Create first admin user
  const user = await userService.createUser({
    username, // Username
    email, // Email
    password, // Password
    full_name, // Full name
    role: 'system_admin', // Always create as system admin for setup
    pin_code, // PIN code (optional)
    active: true, // Active status
  });
  
  // Log system setup (can't log to SystemLog since no user exists yet, but can use logger)
  logger.info(`System initialized with admin user: ${user.username}`, {
    userId: user.id,
    role: user.role,
  });
  
  // Return success response
  return res.status(201).json({
    success: true, // Indicate success
    message: 'System initialized successfully. Admin user created.', // Success message
    data: { user }, // Created user data
  });
});

/**
 * Refresh token controller (placeholder)
 * Refreshes JWT token using refresh token
 * POST /api/auth/refresh
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const refreshToken = asyncHandler(async (req, res) => {
  // TODO: Implement refresh token logic
  // For now, return not implemented error
  return res.status(501).json({
    success: false, // Indicate failure
    message: 'Refresh token not yet implemented', // Error message
  });
});

// Export controller functions
module.exports = {
  login, // Login controller
  loginWithPin, // PIN login controller
  getProfile, // Get profile controller
  setup, // Setup/initialize system controller
  refreshToken, // Refresh token controller
};
