const User = require('../models/userSchema');
const AuditLog = require('../models/auditLogSchema');
const mongoose = require('mongoose');
const Role = require('../models/roleSchema');
const Resource = require('../models/resourceSchema');
const bcypt = require('bcryptjs');
const Tenant = require('../models/tenantSchema');
const generateRandomPassword = require("../utils/generatePassword");
const createUser = async (req, res) => {
  try {
    const { name, email, roleId, isActive } = req.body;

    // Check if email already exists
    const existingUser = await User.findOne({ email });
    if (existingUser) {
      return res.status(409).json({
        error: 'User with this email already exists',
        code: 'EMAIL_EXISTS'
      });
    }

    // Validate role exists
    if(roleId){
    const role = await Role.findById(roleId);
    if (!role || !role.isActive) {
      return res.status(400).json({
        error: 'Invalid or inactive role',
        code: 'INVALID_ROLE'
      });
    }}

    // Validate tenant exists (if provided)
    // let tenant = null;
    // if (tenantId) {
    //   tenant = await Tenant.findById(tenantId);
    //   if (!tenant || !tenant.isActive) {
    //     return res.status(400).json({
    //       error: 'Invalid or inactive tenant',
    //       code: 'INVALID_TENANT'
    //     });
    //   }
    // }

    const password = generateRandomPassword(10);
    console.log("req", req.user);
    // Create user
    const user = new User({
      name: name,
      email: email,
      passwordHash: password, // Will be hashed by pre-save middleware
      role: roleId || null,
      tenantId: req.user?.tenantId._id || null,
      isActive: isActive !== undefined ? isActive : true
    });

    await user.save();

    // Populate the created user
    const populatedUser = await User.findById(user._id)
      .populate('role', 'name')
      .populate('tenantId', 'name code')
      .select('-passwordHash');

    // Log the action
    await AuditLog.create({
      userId: req.user._id,
      action: 'user_created',
      ipAddress: req.ip,
    });

    res.status(201).json({
      message: 'User created successfully',
      user: populatedUser
    });
  } catch (error) {
    console.error('Create user error:', error);
    res.status(500).json({
      error: 'Internal server error',
      code: 'CREATE_USER_FAILED'
    });
  }
}

const getAllUsers = async (req, res) => {
  try {
    const {
      tenantId,
      roleId,
      isActive,
      page = 1,
      limit = 10,
      sortBy = 'createdAt',
      sortOrder = 'desc',
      search
    } = req.query;

    // Build filter
    let filter = {};

    if (tenantId) {
      filter.tenantId = tenantId;
    }

    if (roleId) {
      filter.role = roleId;
    }

    if (isActive !== undefined) {
      filter.isActive = isActive === 'true';
    }

    if (search) {
      filter.$or = [
        { name: { $regex: search, $options: 'i' } },
        { email: { $regex: search, $options: 'i' } }
      ];
    }
    const currentUserId = req?.user?.userId;

    if (req?.user && req?.user?.tenantId) {
            console.log(true);
            filter.tenantId = req?.user?.tenantId._id;
            filter._id = { $ne: currentUserId };
        }

    // Build sort
    const sort = {};
    sort[sortBy] = sortOrder === 'desc' ? -1 : 1;

    // Execute query
    const users = await User.find(filter)
      .populate('role', 'name')
      .populate('tenantId', 'name code')
      .select('-passwordHash')
      .sort(sort)
      .limit(limit * 1)
      .skip((page - 1) * limit);

    const total = await User.countDocuments(filter);

    res.status(200).json({
      users,
      pagination: {
        currentPage: parseInt(page),
        totalPages: Math.ceil(total / limit),
        totalRecords: total,
        limit: parseInt(limit)
      }
    });
  } catch (error) {
    console.error('Get users error:', error);
    res.status(500).json({
      error: 'Internal server error',
      code: 'GET_USERS_FAILED'
    });
  }
}

const GetUserById = async (req, res) => {
  try {
    const { id } = req.params;

    if (!mongoose.Types.ObjectId.isValid(id)) {
      return res.status(400).json({
        error: 'Invalid user ID format',
        code: 'INVALID_USER_ID'
      });
    }

    const user = await User.findById(id)
      .populate('role', 'name permissions')
      .populate('tenantId', 'name code')
      .select('-passwordHash');

    if (!user) {
      return res.status(404).json({
        error: 'User not found',
        code: 'USER_NOT_FOUND'
      });
    }

    return res.status(200).json({
      user,
      message: 'User retrieved successfully'
    });
  } catch (error) {
    console.error('Get user by ID error:', error);
    res.status(500).json({
      error: 'Internal server error',
      code: 'GET_USER_FAILED'
    });
  }
}

const updateUser = async (req, res) => {
  try {
    const { id } = req.params;
    const { name, email, password, roleId, tenantId, isActive } = req.body;

    if (!mongoose.Types.ObjectId.isValid(id)) {
      return res.status(400).json({
        error: 'Invalid user ID format',
        code: 'INVALID_USER_ID'
      });
    }

    const user = await User.findById(id);
    if (!user) {
      return res.status(404).json({
        error: 'User not found',
        code: 'USER_NOT_FOUND'
      });
    }

    // Store original values for audit
    // const originalValues = {
    //   name: user.name,
    //   email: user.email,
    //   role: user.role,
    //   tenantId: user.tenantId,
    //   isActive: user.isActive
    // };

    // Check if email is being changed and if new email exists
    if (email && email !== user.email) {
      const existingUser = await User.findOne({
        email: email.toLowerCase(),
        _id: { $ne: id }
      });
      if (existingUser) {
        return res.status(409).json({
          error: 'Email already exists',
          code: 'EMAIL_EXISTS'
        });
      }
      user.email = email;
    }

    // Validate role if being changed
    if (roleId && roleId !== user?.role?.toString()) {
      const role = await Role.findById(roleId);
      if (!role || !role.isActive) {
        return res.status(400).json({
          error: 'Invalid or inactive role',
          code: 'INVALID_ROLE'
        });
      }
      user.role = roleId;
    }

    // Validate tenant if being changed
    if (tenantId !== undefined && tenantId !== user.tenantId?.toString()) {
      if (tenantId) {
        const tenant = await Tenant.findById(tenantId);
        if (!tenant || !tenant.isActive) {
          return res.status(400).json({
            error: 'Invalid or inactive tenant',
            code: 'INVALID_TENANT'
          });
        }
      }
      user.tenantId = tenantId || null;
    }

    // Update other fields
    if (name !== undefined) user.name = name.trim();
    if (password !== undefined) user.passwordHash = password; // Will be hashed by middleware
    if (isActive !== undefined) user.isActive = isActive;

    await user.save();

    // Get updated user with populated fields
    const updatedUser = await User.findById(id)
      .populate({
        path: 'role',  // Fixed: Added 'path' and corrected 'select' typo
      select: 'name permissions',
      populate: {
        path: 'permissions.resource',  // Nested populate for permissions.resource
        select: 'name'
      }
      })
      .populate('tenantId', 'name code')
      .select('-passwordHash');

    // Log the action
    await AuditLog.create({
      userId: req.user._id,
      action: 'user_updated',
      ipAddress: req.ip,
    });

    res.status(200).json({
      message: 'User updated successfully',
      user: updatedUser
    });
  } catch (error) {
    console.error('Update user error:', error);
    res.status(500).json({
      error: 'Internal server error',
      code: 'UPDATE_USER_FAILED'
    });
  }
}

const deleteUser = async (req, res) => {
  try {
    const { id } = req.params;

    if (!mongoose.Types.ObjectId.isValid(id)) {
      return res.status(400).json({
        error: 'Invalid user ID format',
        code: 'INVALID_USER_ID'
      });
    }

    const user = await User.findById(id);
    if (!user) {
      return res.status(404).json({
        error: 'User not found',
        code: 'USER_NOT_FOUND'
      });
    }

    // Prevent deleting super admin
    const userWithRole = await User.findById(id).populate('role');
    if (userWithRole.role.name === 'super_admin') {
      return res.status(403).json({
        error: 'Cannot delete super admin user',
        code: 'CANNOT_DELETE_SUPER_ADMIN'
      });
    }

    // Soft delete
    user.isActive = false;
    await user.save();

    // Log the action
    await AuditLog.create({
      userId: req.user._id,
      action: 'user_deleted',
      ipAddress: req.ip,
    });

    res.status(200).json({
      message: 'User deactivated successfully',
      user: {
        id: user._id,
        name: user.name,
        email: user.email,
        isActive: user.isActive
      }
    });
  } catch (error) {
    console.error('Delete user error:', error);
    res.status(500).json({
      error: 'Internal server error',
      code: 'DELETE_USER_FAILED'
    });
  }
}

const getUserByTenant = async (req, res) => {
  try {
    const { tenantId } = req.params;
    const { page = 1, limit = 10 } = req.query;

    if (!mongoose.Types.ObjectId.isValid(tenantId)) {
      return res.status(400).json({
        error: 'Invalid tenant ID format',
        code: 'INVALID_TENANT_ID'
      });
    }

    const users = await User.find({ tenantId, isActive: true })
      .populate('role', 'name')
      .populate('tenantId', 'name code')
      .select('-passwordHash')
      .sort({ createdAt: -1 })
      .limit(limit * 1)
      .skip((page - 1) * limit);

    const total = await User.countDocuments({ tenantId, isActive: true });

    res.status(200).json({
      users,
      pagination: {
        currentPage: parseInt(page),
        totalPages: Math.ceil(total / limit),
        totalRecords: total,
        limit: parseInt(limit)
      }
    });
  } catch (error) {
    console.error('Get users by tenant error:', error);
    res.status(500).json({
      error: 'Internal server error',
      code: 'GET_TENANT_USERS_FAILED'
    });
  }
}

module.exports = {
  createUser,
  getAllUsers,
  GetUserById,
  updateUser,
  deleteUser,
  getUserByTenant
};