import { Request, Response } from 'express';

import * as tasksService from '@/modules/tasks/tasks.service';
import catchAsync from '@/shared/utils/catchAsync';
import responseCodes from '@/shared/utils/responseCode/responseCode';
import { pick } from '@/shared/utils';
import ExcelJS from 'exceljs';
import dayjs from 'dayjs';
import * as rulesService from '@/modules/rules/rules.service';
import { UserType } from '@/shared/constants/enum.constant';

const { TasksResponseCodes } = responseCodes;

export const createTasks = catchAsync(async (req: Request, res: Response) => {
  const tasks = await tasksService.createTasks(req.body);
  res.success(tasks, TasksResponseCodes.SUCCESS, 'Tasks Created Successfully');
});

export const updateTasks = catchAsync(async (req: Request, res: Response) => {
  const { id } = pick(req.params, ['id']);

  const updatedTasks = await tasksService.updateTasks(id, req.body);
  res.success(
    updatedTasks,
    TasksResponseCodes.SUCCESS,
    'Tasks Updated Successfully',
  );
});

export const deleteTasksById = catchAsync(
  async (req: Request, res: Response) => {
    const { id } = pick(req.params, ['id']);

    const tasks = await tasksService.deleteTasks(id);
    res.success(
      tasks,
      TasksResponseCodes.SUCCESS,
      'Tasks Deleted Successfully',
    );
  },
);

export const getTasksById = catchAsync(async (req: Request, res: Response) => {
  const { id } = pick(req.params, ['id']);

  const { populate, fields, includeTimeStamps } = pick(req.query, [
    'populate',
    'fields',
    'includeTimeStamps',
  ]);

  const tasks = await tasksService.getTasksById(id, fields, populate);

  const responseData =
    includeTimeStamps === 'true'
      ? tasks.toJSON({ includeTimeStamps: true })
      : tasks;

  // Add activityId if it exists
  if ((tasks as any).activityId) {
    (responseData as any).activityId = (tasks as any).activityId;
  }

  res.success(
    responseData,
    TasksResponseCodes.SUCCESS,
    'Tasks Fetched Successfully',
  );
});

export const getTasks = catchAsync(async (req: Request, res: Response) => {
  const filter = pick(req.query, [
    'status',
    'search',
    'activityType',
    'companyId',
    'assignedTo',
    'activityDate',
    'dueDateFrom',
    'dueDateTo',
  ]);
  const options = pick(req.query, [
    'sortBy',
    'limit',
    'page',
    'populate',
    'includeTimeStamps',
  ]);

  const tasks = await tasksService.queryTasks(filter, options);

  res.success(tasks, TasksResponseCodes.SUCCESS, 'Tasks Fetched Successfully');
});

export const bulkUpdateTasks = catchAsync(
  async (req: Request, res: Response) => {
    const { ids, updateData } = req.body;
    const { firstName, lastName } = req.user;

    const updateDataWithCompany = {
      ...updateData,
      companyId: req.user.company?.id,
      updatedBy: req.user.id,
    };

    const updatedTasks = await tasksService.bulkUpdateTasks(
      ids,
      updateDataWithCompany,
      {
        firstName,
        lastName,
      },
    );

    res.success(
      updatedTasks,
      TasksResponseCodes.SUCCESS,
      `${updatedTasks.length} Task(s) Updated Successfully`,
    );
  },
);

export const bulkDeleteTasks = catchAsync(
  async (req: Request, res: Response) => {
    const { taskIds } = req.body;

    const result = await tasksService.bulkDeleteTasks(taskIds);

    res.success(
      result,
      TasksResponseCodes.SUCCESS,
      `Successfully deleted ${result.deletedCount} tasks`,
    );
  },
);

export const exportTasks = catchAsync(async (req: Request, res: Response) => {
  const filter = pick(req.query, [
    'status',
    'search',
    'activityType',
    'companyId',
    'assignedTo',
    'activityDate',
    'dueDateFrom',
    'dueDateTo',
    'taskIds',
  ]);

  filter.companyId = req.user.company.id;
  const companyId = req.user.company.id;

  const rules = (await rulesService.getRules(
    companyId,
    'export_data',
  )) as Record<string, boolean>;
  const canExport = rules.export_data || req.user.userType === UserType.ADMIN;
  if (!canExport)
    return res.status(403).json({
      message: 'Export not allowed',
      code: TasksResponseCodes.TASKS_ERROR,
    });

  // Query tasks without pagination
  const tasks = await tasksService.queryTasksForExport(filter);

  // Create Excel workbook
  const workbook = new ExcelJS.Workbook();
  const worksheet = workbook.addWorksheet('Tasks');

  // Define columns
  worksheet.columns = [
    { header: 'Status', key: 'status', width: 15 },
    { header: 'Lead Name', key: 'leadName', width: 25 },
    { header: 'Phone Number', key: 'phoneNumber', width: 15 },
    { header: 'Activity', key: 'activity', width: 15 },
    { header: 'Due', key: 'due', width: 15 },
    { header: 'Source', key: 'source', width: 15 },
    { header: 'Preference', key: 'preference', width: 15 },
    { header: 'Assign To', key: 'assignTo', width: 20 },
    { header: 'Created By', key: 'createdBy', width: 20 },
  ];

  // Style the header row
  worksheet.getRow(1).font = { bold: true };
  worksheet.getRow(1).fill = {
    type: 'pattern',
    pattern: 'solid',
    fgColor: { argb: 'FFE6E6FA' },
  };

  // Add data rows
  tasks.forEach((task: any) => {
    const leadName = task.contact
      ? `${task.contact.firstName || ''} ${task.contact.lastName || ''}`.trim()
      : '';

    // Handle phone array - get primary phone or first phone
    let phoneNumber = '';
    if (task.contact?.phone && task.contact.phone.length > 0) {
      const primaryPhone = task.contact.phone.find((p: any) => p.isPrimary);
      const phoneToUse = primaryPhone || task.contact.phone[0];
      phoneNumber =
        phoneToUse.countryCode && phoneToUse.number
          ? `${phoneToUse.countryCode}${phoneToUse.number}`
          : '';
    }

    const assignTo = task.assignedUser
      ? `${task.assignedUser.firstName || ''} ${task.assignedUser.lastName || ''}`.trim()
      : '';

    const createdBy = task.createdByUser
      ? `${task.createdByUser.firstName || ''} ${task.createdByUser.lastName || ''}`.trim()
      : '';

    const preferenceParts = [];
    if (task.configuration && task.configuration.length > 0) {
      preferenceParts.push(task.configuration.join(', '));
    }
    if (task.locality && task.locality.length > 0) {
      preferenceParts.push(task.locality.join(', '));
    }
    const preference =
      preferenceParts.length > 0 ? preferenceParts.join('\n') : '';

    worksheet.addRow({
      status: task.status || '',
      leadName: leadName,
      phoneNumber: phoneNumber,
      activity: task.activityType || '',
      due: task.activityDate
        ? dayjs(task.activityDate).format('DD-MM-YYYY')
        : '',
      source: task.contact?.source?.name || '',
      preference: preference,
      assignTo: assignTo,
      createdBy: createdBy,
    });
  });

  // Set response headers
  res.setHeader(
    'Content-Type',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  );
  res.setHeader(
    'Content-Disposition',
    `attachment; filename=tasks-${dayjs().format('DD-MM-YYYY')}.xlsx`,
  );

  // Write buffer and send
  const buffer = await workbook.xlsx.writeBuffer();
  res.send(buffer);
});
