const Task = require('../models/Task');
const Role = require('../models/Role');
const ActivityLog = require('../models/ActivityLog');
const TaskView = require('../models/TaskView');
// const { sendEmail } = require('../utils/emailService');

// Get all tasks with filtering and pagination
exports.getAllTasks = async (req, res, next) => {
  try {
    const {
      status,
      priority,
      assignedTo,
      assignedBy,
      companyId,
      search,
      page = 1,
      limit = 10,
      sortBy = 'createdAt',
      sortOrder = 'desc'
    } = req.query;

    let query = {};

    // Get current user's role to check scope
    const userRole = await Role.findById(req.user.roleId);

    // Apply restriction: non-global users can only see tasks assigned to them or by them
    if (userRole.scope !== 'global') {
      query.$or = [
        { assignedTo: req.user._id },
        { assignedBy: req.user._id }
      ];
    }

    // Additional filters from query params
    if (status && status !== 'all') query.status = status;
    if (priority && priority !== 'all') query.priority = priority;
    if (assignedTo) query.assignedTo = assignedTo;
    if (assignedBy) query.assignedBy = assignedBy;
    if (companyId) query.companyId = companyId;

    // Search functionality
    if (search && search.trim()) {
      const searchRegex = new RegExp(search.trim(), 'i');
      query.$and = query.$and || [];
      query.$and.push({
        $or: [
          { title: searchRegex },
          { description: searchRegex }
        ]
      });
    }

    // Pagination
    const pageNum = Math.max(1, parseInt(page));
    const limitNum = Math.max(1, parseInt(limit));
    const skip = (pageNum - 1) * limitNum;

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

    const [tasks, totalTasks] = await Promise.all([
      Task.find(query)
        .populate('assignedTo', 'firstName lastName email')
        .populate('assignedBy', 'firstName lastName email')
        .populate('companyId', 'name')
        .sort(sort)
        .limit(limitNum)
        .skip(skip)
        .lean(),
      Task.countDocuments(query)
    ]);

    // Transform tasks to include fullName for assignedTo/assignedBy to match frontend interface
    const transformedTasks = tasks.map(task => ({
      ...task,
      assignedTo: task.assignedTo ? {
        ...task.assignedTo,
        fullName: `${task.assignedTo.firstName} ${task.assignedTo.lastName}`
      } : null,
      assignedBy: task.assignedBy ? {
        ...task.assignedBy,
        fullName: `${task.assignedBy.firstName} ${task.assignedBy.lastName}`
      } : null
    }));

    // ✅ Update TaskView to mark as seen (only if clearUnseen is true)
    if (req.query.clearUnseen === 'true') {
      await TaskView.findOneAndUpdate(
        { userId: req.user._id },
        { lastViewedAt: new Date() },
        { upsert: true, new: true }
      );
    }

    res.status(200).json({
      success: true,
      data: {
        tasks: transformedTasks,
        pagination: {
          currentPage: pageNum,
          totalPages: Math.ceil(totalTasks / limitNum),
          totalTasks,
          limit: limitNum
        }
      }
    });
  } catch (error) {
    next(error);
  }
};

/**
 * ✅ Get unseen tasks count for the current user
 */
exports.getUnseenCount = async (req, res, next) => {
  try {
    const view = await TaskView.findOne({ userId: req.user._id });
    const lastViewedAt = view ? view.lastViewedAt : new Date(0);

    const count = await Task.countDocuments({
      assignedTo: req.user._id,
      status: { $nin: ['completed', 'closed', 'accepted'] }, // Only count active tasks
      createdBy: { $ne: req.user._id }, // ✅ Except the one who created the task
      createdAt: { $gt: lastViewedAt }
    });

    res.status(200).json({
      success: true,
      data: { count }
    });
  } catch (error) {
    next(error);
  }
};

// Get single task
exports.getTaskById = async (req, res, next) => {
  try {
    const task = await Task.findById(req.params.id)
      .populate('assignedTo', 'firstName lastName email')
      .populate('assignedBy', 'firstName lastName email')
      .populate('companyId', 'name');

    if (!task) {
      return res.status(404).json({
        success: false,
        message: 'Task not found'
      });
    }

    // Access control: Check if user can see this task
    const userRole = await Role.findById(req.user.roleId);
    if (userRole.scope !== 'global') {
      const isAssigned = task.assignedTo?._id.toString() === req.user._id.toString() || 
                         task.assignedBy?._id.toString() === req.user._id.toString();
      const isInCompany = req.user.companies.some(c => c.toString() === task.companyId?.toString());
      
      if (!isAssigned && !isInCompany) {
        return res.status(403).json({
          success: false,
          message: 'Access denied'
        });
      }
    }

    // Transform for frontend
    const taskObj = task.toObject();
    if (taskObj.assignedTo) taskObj.assignedTo.fullName = `${taskObj.assignedTo.firstName} ${taskObj.assignedTo.lastName}`;
    if (taskObj.assignedBy) taskObj.assignedBy.fullName = `${taskObj.assignedBy.firstName} ${taskObj.assignedBy.lastName}`;

    res.status(200).json({
      success: true,
      data: { task: taskObj }
    });
  } catch (error) {
    next(error);
  }
};

// Create task
exports.createTask = async (req, res, next) => {
  try {
    const taskData = {
      ...req.body,
      assignedTo: req.body.assignedTo || req.user._id, // Default to self if not provided
      assignedBy: req.user._id,
      createdBy: req.user._id
    };

    const task = await Task.create(taskData);

    // Log activity
    await ActivityLog.create({
      userId: req.user._id,
      companyId: task.companyId || req.user.companies?.[0],
      action: 'create',
      module: 'tasks',
      entityType: 'Task',
      entityId: task._id,
      description: `Created task: ${task.title}`
    });

    const populatedTask = await Task.findById(task._id)
      .populate('assignedTo', 'firstName lastName email')
      .populate('assignedBy', 'firstName lastName email')
      .populate('companyId', 'name');

    const taskObj = populatedTask.toObject();
    if (taskObj.assignedTo) taskObj.assignedTo.fullName = `${taskObj.assignedTo.firstName} ${taskObj.assignedTo.lastName}`;
    if (taskObj.assignedBy) taskObj.assignedBy.fullName = `${taskObj.assignedBy.firstName} ${taskObj.assignedBy.lastName}`;

    /*
    // ✅ Send email to assigned user if not self-assigned
    try {
      const assignedToId = task.assignedTo.toString();
      const creatorId = req.user._id.toString();

      if (assignedToId !== creatorId && populatedTask.assignedTo && populatedTask.assignedTo.email) {
        const assignee = populatedTask.assignedTo;
        const assignerName = `${populatedTask.assignedBy.firstName} ${populatedTask.assignedBy.lastName}`;
        const companyName = populatedTask.companyId ? populatedTask.companyId.name : 'Arihant Industries';

        sendEmail({
          to: assignee.email,
          subject: `New Task Assigned: ${task.title}`,
          text: `Hi ${assignee.firstName},\n\nA new task "${task.title}" has been assigned to you by ${assignerName}.\n\nPriority: ${task.priority}\nDue Date: ${task.dueDate ? new Date(task.dueDate).toLocaleDateString() : 'No due date'}\nDescription: ${task.description || 'No description provided'}\n\nYou can view and update this task in your dashboard.\n\nBest regards,\nArihant Industries Team`,
          html: `
            <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e0e0e0; border-radius: 8px;">
              <h2 style="color: #2980b9;">New Task Assigned</h2>
              <p>Hi ${assignee.firstName},</p>
              <p>A new task <strong>"${task.title}"</strong> has been assigned to you by <strong>${assignerName}</strong>.</p>
              <div style="background-color: #f9f9f9; padding: 15px; border-radius: 5px; margin: 20px 0;">
                <p style="margin: 5px 0;"><strong>Company:</strong> ${companyName}</p>
                <p style="margin: 5px 0;"><strong>Priority:</strong> <span style="text-transform: capitalize; color: ${task.priority === 'urgent' ? '#e74c3c' : (task.priority === 'high' ? '#e67e22' : '#2ecc71')};">${task.priority}</span></p>
                <p style="margin: 5px 0;"><strong>Due Date:</strong> ${task.dueDate ? new Date(task.dueDate).toLocaleDateString() : 'No due date'}</p>
                <p style="margin: 5px 0;"><strong>Description:</strong> ${task.description || 'No description provided'}</p>
              </div>
              <p>Please log in to your dashboard to view the details and update the status.</p>
              <div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #eeeeee; font-size: 12px; color: #7f8c8d;">
                <p>This is an automated notification from Arihant Industries CRM.</p>
              </div>
            </div>
          `
        }).catch(err => console.error("Failed to send task notification email:", err));
      }
    } catch (emailError) {
      console.error("Error in task email notification process:", emailError);
    }
    */

    res.status(201).json({
      success: true,
      message: 'Task created successfully',
      data: { task: taskObj }
    });
  } catch (error) {
    next(error);
  }
};

// Update task
exports.updateTask = async (req, res, next) => {
  try {
    const task = await Task.findById(req.params.id);
    if (!task) {
      return res.status(404).json({
        success: false,
        message: 'Task not found'
      });
    }

    // Access control: Only assigner or global admin or assigned user (limiting update)
    const userRole = await Role.findById(req.user.roleId);
    if (userRole.scope !== 'global' && task.assignedBy.toString() !== req.user._id.toString()) {
        // If not assigner, maybe they are the assignee just wanting to update status?
        // We'll allow status updates in a separate method or here with restrictions
        if (task.assignedTo.toString() !== req.user._id.toString()) {
            return res.status(403).json({
              success: false,
              message: 'Not authorized to update this task'
            });
        }
    }

    const updates = { 
      ...req.body, 
      assignedTo: req.body.assignedTo || req.user._id,
      updatedBy: req.user._id 
    };
    
    const updatedTask = await Task.findByIdAndUpdate(req.params.id, updates, {
      new: true,
      runValidators: true
    })
      .populate('assignedTo', 'firstName lastName email')
      .populate('assignedBy', 'firstName lastName email')
      .populate('companyId', 'name');

    // Log activity
    await ActivityLog.create({
      userId: req.user._id,
      companyId: updatedTask.companyId || req.user.companies?.[0],
      action: 'update',
      module: 'tasks',
      entityType: 'Task',
      entityId: updatedTask._id,
      description: `Updated task: ${updatedTask.title}`,
      changes: updates
    });

    const taskObj = updatedTask.toObject();
    if (taskObj.assignedTo) taskObj.assignedTo.fullName = `${taskObj.assignedTo.firstName} ${taskObj.assignedTo.lastName}`;
    if (taskObj.assignedBy) taskObj.assignedBy.fullName = `${taskObj.assignedBy.firstName} ${taskObj.assignedBy.lastName}`;

    res.status(200).json({
      success: true,
      message: 'Task updated successfully',
      data: { task: taskObj }
    });
  } catch (error) {
    next(error);
  }
};

// Update status only
exports.updateTaskStatus = async (req, res, next) => {
  try {
    const { status } = req.body;
    const task = await Task.findById(req.params.id);

    if (!task) {
      return res.status(404).json({
        success: false,
        message: 'Task not found'
      });
    }

    // Anyone assigned to or by the task can update status
    const isAssigned = task.assignedTo?.toString() === req.user._id.toString() || 
                       task.assignedBy?.toString() === req.user._id.toString();
    
    const userRole = await Role.findById(req.user.roleId);
    if (userRole.scope !== 'global' && !isAssigned) {
      return res.status(403).json({
        success: false,
        message: 'Not authorized'
      });
    }

    task.status = status;
    task.updatedBy = req.user._id;
    await task.save();

    res.status(200).json({
      success: true,
      message: 'Task status updated'
    });
  } catch (error) {
    next(error);
  }
};

// Delete task
exports.deleteTask = async (req, res, next) => {
  try {
    const task = await Task.findById(req.params.id);
    if (!task) {
      return res.status(404).json({
        success: false,
        message: 'Task not found'
      });
    }

    // Only creator or global admin can delete
    const userRole = await Role.findById(req.user.roleId);
    if (userRole.scope !== 'global' && task.assignedBy.toString() !== req.user._id.toString()) {
      return res.status(403).json({
        success: false,
        message: 'Not authorized to delete this task'
      });
    }

    await Task.findByIdAndDelete(req.params.id);

    // Log activity
    await ActivityLog.create({
      userId: req.user._id,
      companyId: task.companyId || req.user.companies?.[0],
      action: 'delete',
      module: 'tasks',
      entityType: 'Task',
      entityId: task._id,
      description: `Deleted task: ${task.title}`
    });

    res.status(200).json({
      success: true,
      message: 'Task deleted successfully'
    });
  } catch (error) {
    next(error);
  }
};
