const Company = require('../models/Company');
const User = require('../models/User');
const Role = require('../models/Role');
const ActivityLog = require('../models/ActivityLog');

// Get all companies
exports.getAllCompanies = async (req, res, next) => {
  try {
    const { status, search, page = 1, limit = 10 } = req.query;
    
    // Build query
    let query = {};
    
    // Scope restriction: Non-global users can only see their assigned companies
    const userRole = await Role.findById(req.user.roleId);
    if (userRole && userRole.scope !== 'global') {
      const assignedCompanyIds = req.user.companies.map(c => c._id);
      query._id = { $in: assignedCompanyIds };
    }
    
    // Filter by status
    if (status) {
      query.status = status;
    }
    
    // Search by name or code
    if (search) {
      query.$or = [
        { name: { $regex: search, $options: 'i' } },
        { code: { $regex: search, $options: 'i' } }
      ];
    }
    
    // Pagination
    const skip = (page - 1) * limit;
    
    const companies = await Company.find(query)
      .populate('createdBy', 'firstName lastName email')
      .sort({ createdAt: -1 })
      .limit(parseInt(limit))
      .skip(skip);
    
    const total = await Company.countDocuments(query);
    
    res.status(200).json({
      success: true,
      count: companies.length,
      total,
      page: parseInt(page),
      pages: Math.ceil(total / limit),
      data: companies
    });
  } catch (error) {
    next(error);
  }
};

// Get single company
exports.getCompany = async (req, res, next) => {
  try {
    const { id } = req.params;
    
    const company = await Company.findById(id)
      .populate('createdBy', 'firstName lastName email');
    
    if (!company) {
      return res.status(404).json({
        success: false,
        message: 'Company not found'
      });
    }
    
    // Get company statistics
    const userCount = await User.countDocuments({ companyId: id });
    const activeUserCount = await User.countDocuments({ companyId: id, status: 'active' });
    
    res.status(200).json({
      success: true,
      data: {
        ...company.toObject(),
        stats: {
          totalUsers: userCount,
          activeUsers: activeUserCount
        }
      }
    });
  } catch (error) {
    next(error);
  }
};

// Create company
exports.createCompany = async (req, res, next) => {
  try {
    const {
      name,
      code,
      status,
      contact,
      settings
    } = req.body;
    
    // Check if company code already exists
    const existingCompany = await Company.findOne({ code: code.toUpperCase() });
    if (existingCompany) {
      return res.status(400).json({
        success: false,
        message: 'Company code already exists'
      });
    }
    
    // Create company
    const company = await Company.create({
      name,
      code: code.toUpperCase(),
      status,
      contact,
      settings,
      createdBy: req.user._id
    });
    
    // Log activity
    await ActivityLog.create({
      userId: req.user._id,
      companyId: company._id,
      action: 'create',
      module: 'companies',
      entityType: 'Company',
      entityId: company._id,
      description: `Created company: ${company.name} (${company.code})`,
      ipAddress: req.ip,
      userAgent: req.get('user-agent')
    });
    
    const populatedCompany = await Company.findById(company._id)
      .populate('createdBy', 'firstName lastName email');
    
    res.status(201).json({
      success: true,
      message: 'Company created successfully',
      data: populatedCompany
    });
  } catch (error) {
    next(error);
  }
};

// Update company
exports.updateCompany = async (req, res, next) => {
  try {
    const { id } = req.params;
    const updates = req.body;
    
    // Don't allow updating company code
    delete updates.code;
    
    const company = await Company.findByIdAndUpdate(
      id,
      updates,
      { new: true, runValidators: true }
    ).populate('createdBy', 'firstName lastName email');
    
    if (!company) {
      return res.status(404).json({
        success: false,
        message: 'Company not found'
      });
    }
    
    // Log activity
    await ActivityLog.create({
      userId: req.user._id,
      companyId: company._id,
      action: 'update',
      module: 'companies',
      entityType: 'Company',
      entityId: company._id,
      description: `Updated company: ${company.name}`,
      changes: updates,
      ipAddress: req.ip,
      userAgent: req.get('user-agent')
    });
    
    res.status(200).json({
      success: true,
      message: 'Company updated successfully',
      data: company
    });
  } catch (error) {
    next(error);
  }
};

// Delete company
exports.deleteCompany = async (req, res, next) => {
  try {
    const { id } = req.params;
    
    const company = await Company.findById(id);
    
    if (!company) {
      return res.status(404).json({
        success: false,
        message: 'Company not found'
      });
    }
    
    // Check if company has users
    const userCount = await User.countDocuments({ companyId: id });
    if (userCount > 0) {
      return res.status(400).json({
        success: false,
        message: `Cannot delete company. ${userCount} user(s) are assigned to this company. Please reassign or delete users first.`
      });
    }
    
    await Company.findByIdAndDelete(id);
    
    // Log activity
    await ActivityLog.create({
      userId: req.user._id,
      action: 'delete',
      module: 'companies',
      entityType: 'Company',
      entityId: company._id,
      description: `Deleted company: ${company.name} (${company.code})`,
      ipAddress: req.ip,
      userAgent: req.get('user-agent')
    });
    
    res.status(200).json({
      success: true,
      message: 'Company deleted successfully'
    });
  } catch (error) {
    next(error);
  }
};

// Update company status (activate/deactivate/suspend)
exports.updateCompanyStatus = async (req, res, next) => {
  try {
    const { id } = req.params;
    const { status } = req.body;
    
    if (!['active', 'inactive', 'suspended'].includes(status)) {
      return res.status(400).json({
        success: false,
        message: 'Invalid status. Must be: active, inactive, or suspended'
      });
    }
    
    const company = await Company.findByIdAndUpdate(
      id,
      { status },
      { new: true }
    ).populate('createdBy', 'firstName lastName email');
    
    if (!company) {
      return res.status(404).json({
        success: false,
        message: 'Company not found'
      });
    }
    
    // If suspending, also suspend all company users
    if (status === 'suspended') {
      await User.updateMany(
        { companyId: id },
        { status: 'suspended' }
      );
    }
    
    // Log activity
    await ActivityLog.create({
      userId: req.user._id,
      companyId: company._id,
      action: 'update',
      module: 'companies',
      entityType: 'Company',
      entityId: company._id,
      description: `Changed company status to: ${status}`,
      changes: { status },
      ipAddress: req.ip,
      userAgent: req.get('user-agent')
    });
    
    res.status(200).json({
      success: true,
      message: `Company status updated to ${status}`,
      data: company
    });
  } catch (error) {
    next(error);
  }
};

// Get company users
exports.getCompanyUsers = async (req, res, next) => {
  try {
    const { id } = req.params;
    const { status, role, page = 1, limit = 10 } = req.query;
    
    // Check if company exists
    const company = await Company.findById(id);
    if (!company) {
      return res.status(404).json({
        success: false,
        message: 'Company not found'
      });
    }
    
    // Build query
    let query = { companyId: id };
    
    if (status) {
      query.status = status;
    }
    
    if (role) {
      const roleDoc = await Role.findOne({ name: role });
      if (roleDoc) {
        query.roleId = roleDoc._id;
      }
    }
    
    // Pagination
    const skip = (page - 1) * limit;
    
    const users = await User.find(query)
      .populate('roleId', 'name displayName')
      .select('-password -refreshToken')
      .sort({ createdAt: -1 })
      .limit(parseInt(limit))
      .skip(skip);
    
    const total = await User.countDocuments(query);
    
    res.status(200).json({
      success: true,
      company: {
        id: company._id,
        name: company.name,
        code: company.code
      },
      count: users.length,
      total,
      page: parseInt(page),
      pages: Math.ceil(total / limit),
      data: users
    });
  } catch (error) {
    next(error);
  }
};

// Get company statistics
exports.getCompanyStats = async (req, res, next) => {
  try {
    const { id } = req.params;
    
    // Check if company exists
    const company = await Company.findById(id);
    if (!company) {
      return res.status(404).json({
        success: false,
        message: 'Company not found'
      });
    }
    
    // Get user statistics
    const totalUsers = await User.countDocuments({ companyId: id });
    const activeUsers = await User.countDocuments({ companyId: id, status: 'active' });
    const inactiveUsers = await User.countDocuments({ companyId: id, status: 'inactive' });
    const suspendedUsers = await User.countDocuments({ companyId: id, status: 'suspended' });
    
    // Get users by role
    const usersByRole = await User.aggregate([
      { $match: { companyId: company._id } },
      {
        $lookup: {
          from: 'roles',
          localField: 'roleId',
          foreignField: '_id',
          as: 'role'
        }
      },
      { $unwind: '$role' },
      {
        $group: {
          _id: '$role.displayName',
          count: { $sum: 1 }
        }
      },
      { $sort: { count: -1 } }
    ]);
    
    // Get recent activity
    const recentActivity = await ActivityLog.find({ companyId: id })
      .populate('userId', 'firstName lastName email')
      .sort({ createdAt: -1 })
      .limit(10);
    
    res.status(200).json({
      success: true,
      data: {
        company: {
          id: company._id,
          name: company.name,
          code: company.code,
          status: company.status
        },
        users: {
          total: totalUsers,
          active: activeUsers,
          inactive: inactiveUsers,
          suspended: suspendedUsers,
          byRole: usersByRole
        },
        recentActivity
      }
    });
  } catch (error) {
    next(error);
  }
};

// Update company settings
exports.updateCompanySettings = async (req, res, next) => {
  try {
    const { id } = req.params;
    const { settings } = req.body;
    
    const company = await Company.findByIdAndUpdate(
      id,
      { settings },
      { new: true, runValidators: true }
    ).populate('createdBy', 'firstName lastName email');
    
    if (!company) {
      return res.status(404).json({
        success: false,
        message: 'Company not found'
      });
    }
    
    // Log activity
    await ActivityLog.create({
      userId: req.user._id,
      companyId: company._id,
      action: 'update',
      module: 'companies',
      entityType: 'Company',
      entityId: company._id,
      description: `Updated company settings`,
      changes: { settings },
      ipAddress: req.ip,
      userAgent: req.get('user-agent')
    });
    
    res.status(200).json({
      success: true,
      message: 'Company settings updated successfully',
      data: company
    });
  } catch (error) {
    next(error);
  }
};