const jwt = require('jsonwebtoken');
const { executeQuery } = require('../config/database');

const legacyRoleMap = {
  super_admin: 'main_admin',
  company_admin: 'admin',
  sub_admin: 'admin',
  manager: 'user',
  team_leader: 'user',
  developer: 'user',
  designer: 'user',
  tester: 'user',
  analyst: 'user',
  employee: 'user'
};

const rolePermissionLevel = {
  main_admin: 3,
  admin: 2,
  user: 1
};

const normalizeRole = (role) => legacyRoleMap[role] || role || 'user';

const normalizeUserRecord = async (user) => {
  if (!user) return user;

  const normalizedRole = normalizeRole(user.role);
  const expectedLevel = rolePermissionLevel[normalizedRole] || 1;
  const currentLevel = Number.isInteger(user.permission_level)
    ? user.permission_level
    : expectedLevel;

  let shouldPersist = false;

  if (normalizedRole !== user.role) {
    user.role = normalizedRole;
    shouldPersist = true;
  }

  if (currentLevel !== expectedLevel) {
    user.permission_level = expectedLevel;
    shouldPersist = true;
  } else {
    user.permission_level = currentLevel;
  }

  if (shouldPersist) {
    await executeQuery(
      'UPDATE users SET role = ?, permission_level = ?, updated_at = NOW() WHERE id = ?',
      [user.role, user.permission_level, user.id]
    );
  }

  return user;
};

// Verify JWT token
const authenticateToken = async (req, res, next) => {
  let token;
  try {
    const authHeader = req.headers['authorization'];
    token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN

    if (!token) {
      return res.status(401).json({
        success: false,
        message: 'Access token required'
      });
    }

    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    
    // Get user with company information
    const userQuery = `
      SELECT u.*, c.name as company_name
      FROM users u
      LEFT JOIN companies c ON u.company_id = c.id
      WHERE u.id = ? AND u.status = 'active'
    `;
    
    const users = await executeQuery(userQuery, [decoded.userId]);

    if (users.length === 0) {
      return res.status(401).json({
        success: false,
        message: 'Invalid token or user not found'
      });
    }

    req.user = await normalizeUserRecord(users[0]);
    next();
  } catch (error) {
    console.error('authenticateToken error:', error?.name, error?.message, {
      tokenPreview: token ? `${token.substring(0, 10)}...` : null,
    });
    if (error.name === 'TokenExpiredError') {
      return res.status(401).json({
        success: false,
        message: 'Token expired'
      });
    }
    
    return res.status(403).json({
      success: false,
      message: 'Invalid token'
    });
  }
};

// Check if user has required permission level
const requirePermissionLevel = (levels) => {
  return (req, res, next) => {
    if (!req.user) {
      return res.status(401).json({
        success: false,
        message: 'Authentication required'
      });
    }

    const userLevel = req.user.permission_level;
    const userRole = req.user.role;
    const allowedLevels = Array.isArray(levels) ? levels : [levels];

    const hasPermission = allowedLevels.includes(userLevel) ||
      (typeof userRole === 'string' && allowedLevels.includes(userRole));

    if (!hasPermission) {
      return res.status(403).json({
        success: false,
        message: 'Insufficient permissions'
      });
    }

    next();
  };
};

// Check if user is main admin
const requireMainAdmin = requirePermissionLevel(['main_admin']);

// Check if user is admin or main admin
const requireCompanyAdmin = requirePermissionLevel(['main_admin', 'admin']);

// Backward-compatible helper for routes that previously allowed managers
const requireManager = requireCompanyAdmin;

// Legacy role function for backward compatibility
const requireRole = requirePermissionLevel;
const requireAdmin = requireCompanyAdmin;
const requireSuperAdmin = requireMainAdmin;

// Optional authentication (doesn't fail if no token)
const optionalAuth = async (req, res, next) => {
  try {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1];

    if (token) {
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      const user = await executeQuery(
        'SELECT id, phone_number, first_name, last_name, role, status, permission_level FROM users WHERE id = ? AND status = "active"',
        [decoded.userId]
      );

      if (user.length > 0) {
        req.user = await normalizeUserRecord(user[0]);
      }
    }
    
    next();
  } catch (error) {
    // Continue without authentication
    next();
  }
};

module.exports = {
  authenticateToken,
  requirePermissionLevel,
  requireMainAdmin,
  requireCompanyAdmin,
  requireManager,
  requireRole,
  requireAdmin,
  requireSuperAdmin,
  optionalAuth
};
