import { Campaign, CampaignLog, Contact, Sender } from "@prisma/client";
import { CampaignWithSender } from "./campaigns-repository";

export interface CampaignLogStatusCounts {
  total: number;
  success: number;
  failed: number;
  pending: number;
}

export interface LogTimeSeriesPoint {
  date: string;
  label: string;
  envios: number;
  aberturas: number;
  cliques: number;
}

export interface DomainProviderStats {
  name: string;
  deliveredRate: number;
  total: number;
  success: number;
}

export type CampaignLogWithCampaignAndSenderName = CampaignLog & {
  campaign: Campaign & { sender: Pick<Sender, "name" | "fromEmail"> };
};

export interface FindByContactIdOptions {
  skip: number;
  take: number;
  status?: "opened" | "unopened";
}

export interface CampaignLogsRepository {
  upsertPending(campaignId: string, contactId: string): Promise<CampaignLog>;
  markSuccess(logId: string): Promise<void>;
  markFailed(logId: string, errorMessage: string): Promise<void>;
  incrementRetryCount(logId: string): Promise<void>;
  updateMessageId(logId: string, messageId: string): Promise<void>;
  findByMessageId(messageId: string): Promise<(CampaignLog & { contact: Contact }) | null>;
  findFailedByCampaignId(campaignId: string): Promise<(CampaignLog & { contact: Contact })[]>;
  countFailedByCampaignId(campaignId: string): Promise<number>;
  countByStatusForCampaignIds(campaignIds: string[]): Promise<CampaignLogStatusCounts>;
  findLogsForAnalytics(campaignIds: string[], startDate?: Date, endDate?: Date): Promise<Array<{
    id: string;
    status: string;
    createdAt: Date;
    sentAt: Date | null;
    retryCount: number;
    contact: { email: string };
  }>>;
  /** Usado pelo endpoint do pixel de rastreamento — busca leve, só as FKs necessárias para gravar o EmailEvent. */
  findCampaignAndContactIdsByLogId(
    logId: string
  ): Promise<{ campaignId: string; contactId: string } | null>;
  /** Usado pelo reenvio pontual de campanha — precisa do remetente completo para montar o MailProvider. */
  findByIdWithCampaignAndContact(
    logId: string
  ): Promise<(CampaignLog & { campaign: CampaignWithSender; contact: Contact }) | null>;
  findByContactId(
    contactId: string,
    options: FindByContactIdOptions
  ): Promise<CampaignLogWithCampaignAndSenderName[]>;
  countByContactId(contactId: string, options: { status?: "opened" | "unopened" }): Promise<number>;
}

