import { Contact } from "@prisma/client";
import { AppError } from "@/core/errors/app-error";
import { CampaignLogsRepository } from "@/modules/campaigns/repositories/campaign-logs-repository";
import { EmailEventsRepository } from "@/modules/ses-webhooks/repositories/email-events-repository";
import { ContactsRepository } from "../repositories/contacts-repository";
import {
  ContactEmailHistoryItem,
  mapCampaignLogToEmailHistoryItem,
} from "../entities/map-campaign-log-to-email-history-item";

// Limite de segurança para o export não-paginado — evita uma consulta/resposta sem tamanho previsível.
const EXPORT_ROW_CAP = 5000;

interface ExportContactEmailHistoryUseCaseRequest {
  contactId: string;
  status?: "opened" | "unopened";
}

interface ExportContactEmailHistoryUseCaseResponse {
  contact: Contact;
  items: ContactEmailHistoryItem[];
}

export class ExportContactEmailHistoryUseCase {
  constructor(
    private contactsRepository: ContactsRepository,
    private campaignLogsRepository: CampaignLogsRepository,
    private emailEventsRepository: EmailEventsRepository
  ) {}

  async execute({
    contactId,
    status,
  }: ExportContactEmailHistoryUseCaseRequest): Promise<ExportContactEmailHistoryUseCaseResponse> {
    const contact = await this.contactsRepository.findById(contactId);
    if (!contact) {
      throw AppError.notFound("Contato não encontrado");
    }

    const logs = await this.campaignLogsRepository.findByContactId(contactId, {
      skip: 0,
      take: EXPORT_ROW_CAP,
      status,
    });

    const campaignIds = [...new Set(logs.map((log) => log.campaignId))];
    const engagement = await this.emailEventsRepository.findEngagementByContactAndCampaignIds(
      contactId,
      campaignIds
    );
    const engagementByCampaignId = new Map(engagement.map((entry) => [entry.campaignId, entry]));

    const items = logs.map((log) =>
      mapCampaignLogToEmailHistoryItem(log, contact.email, engagementByCampaignId.get(log.campaignId))
    );

    return { contact, items };
  }
}
