// Create contact service functions
import { Request, Response } from 'express';
import * as contactService from '@/modules/contacts/contacts.service';
import catchAsync from '@/shared/utils/catchAsync';
import responseCodes from '@/shared/utils/responseCode/responseCode';
import { pick } from '@/shared/utils';
import { createBrevoContact } from '@/shared/brevo/brevoContactService';
import ExcelJS from 'exceljs';
import * as rulesService from '@/modules/rules/rules.service';
import { UserType } from '@/shared/constants/enum.constant';

const { ContactResponseCodes } = responseCodes;

export const createContact = catchAsync(async (req: Request, res: Response) => {
  const contact = await contactService.createContact(req.body);
  createBrevoContact({
    email: contact.email,
    sms: `${contact?.phone?.[0].countryCode}${contact?.phone?.[0]?.number}`,
    attributes: contact.toJSON(),
  });
  res.success(
    contact,
    ContactResponseCodes.SUCCESS,
    'Contact Created Successfully',
  );
});

export const updateContact = catchAsync(async (req: Request, res: Response) => {
  const { id } = pick(req.params, ['id']);
  const updatedContact = await contactService.updateContact(id, req.body);
  const contact = await contactService.getContactById(id);
  createBrevoContact({
    email: contact.email,
    sms: `${contact?.phone?.[0].countryCode}${contact?.phone?.[0]?.number}`,
    attributes: contact.toJSON(),
    updateExisting: true,
  });
  res.success(
    updatedContact,
    ContactResponseCodes.SUCCESS,
    'Contact Updated Successfully',
  );
});

export const getContactById = catchAsync(
  async (req: Request, res: Response) => {
    const { id } = pick(req.params, ['id']);
    const contact = await contactService.getContactById(id);
    res.success(
      contact,
      ContactResponseCodes.SUCCESS,
      'Contact Fetched Successfully',
    );
  },
);

export const getContacts = catchAsync(async (req: Request, res: Response) => {
  const filter = pick(req.query, ['company', 'source', 'companyId', 'search', 'createdBy']);
  const options = pick(req.query, [
    'sortBy',
    'limit',
    'page',
    'fields',
    'populate',
    'includeTimeStamps',
    'alias',
  ]);

  const contacts = await contactService.queryContacts(filter, options);
  res.success(
    contacts,
    ContactResponseCodes.SUCCESS,
    'Contacts Fetched Successfully',
  );
});

export const exportContacts = catchAsync(async (req: Request, res: Response) => {
  const filter = pick(req.query, [
    'company',
    'source',
    'companyId',
    'search',
    'createdBy',
    'ids',
  ]);
  filter.companyId = req.user?.company?.id ?? filter.companyId;
  const companyId = req.user?.company?.id;

  if (!companyId) {
    return res.status(400).json({
      message: 'Company context required for export',
      code: ContactResponseCodes.CONTACT_ERROR,
    });
  }

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

  const options = {
    limit: 10000,
    page: 1,
    populate: 'source:name;createdBy:firstName,lastName',
    fields: 'firstName lastName email phone source createdBy createdAt updatedAt',
  };

  const result = await contactService.queryContacts(filter, options);
  const contacts = result.results ?? result.docs ?? [];

  const workbook = new ExcelJS.Workbook();
  const worksheet = workbook.addWorksheet('Contacts');
  worksheet.columns = [
    { header: 'Name', key: 'name', width: 28 },
    { header: 'Phone Number', key: 'phoneNumber', width: 18 },
    { header: 'Source', key: 'source', width: 18 },
    { header: 'Created By', key: 'createdBy', width: 22 },
    { header: 'Created On', key: 'createdOn', width: 14 },
    { header: 'Last Contacted', key: 'lastContacted', width: 16 },
  ];

  contacts.forEach((contact: any) => {
    const name = [contact.firstName, contact.lastName].filter(Boolean).join(' ').trim() || '';
    const primaryPhone = contact.phone?.find((p: any) => p.isPrimary) || contact.phone?.[0];
    const phoneNumber = primaryPhone
      ? `+${primaryPhone.countryCode} ${primaryPhone.number}`
      : '';
    const sourceName = contact.source?.name ?? (typeof contact.source === 'string' ? contact.source : '') ?? '';
    const createdByName = contact.createdBy
      ? `${contact.createdBy.firstName || ''} ${contact.createdBy.lastName || ''}`.trim()
      : '';
    const createdOn = contact.createdAt
      ? new Date(contact.createdAt).toLocaleDateString('en-IN', {
          day: '2-digit',
          month: 'short',
          year: 'numeric',
        })
      : '';
    const lastContacted = contact.updatedAt
      ? new Date(contact.updatedAt).toLocaleDateString('en-IN', {
          day: '2-digit',
          month: 'short',
          year: 'numeric',
        })
      : '';

    worksheet.addRow({
      name,
      phoneNumber,
      source: sourceName,
      createdBy: createdByName,
      createdOn,
      lastContacted,
    });
  });

  res.setHeader(
    'Content-Type',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  );
  res.setHeader('Content-Disposition', 'attachment; filename=contacts.xlsx');
  const buffer = await workbook.xlsx.writeBuffer();
  res.send(buffer);
});

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

    const company = await contactService.deleteContact(id);
    res.success(
      company,
      ContactResponseCodes.SUCCESS,
      'Company Deleted Successfully',
    );
  },
);

export const checkIfRefContact = catchAsync(async (req: Request, res: Response) => {
  const { id } = pick(req.params, ['id']);
  await contactService.checkIfRefContact(id);
  res.success(
    null,
    ContactResponseCodes.SUCCESS,
    'Ref Contact Checked Successfully',
  );
});
