import { Campaign, CampaignStatus } from "@prisma/client";
import { prisma } from "@/shared/infra/prisma/prisma-client";
import { CreateCampaignDTO } from "../dtos/create-campaign-dto";
import { UpdateCampaignDTO } from "../dtos/update-campaign-dto";
import {
  CampaignsRepository,
  CampaignWithLogsAndSender,
  CampaignWithSender,
  CampaignWithSenderName,
} from "./campaigns-repository";

export class PrismaCampaignsRepository implements CampaignsRepository {
  async create(data: CreateCampaignDTO): Promise<Campaign> {
    return prisma.campaign.create({
      data: {
        title: data.title,
        subject: data.subject,
        htmlBody: data.htmlBody,
        senderId: data.senderId!,
        contactListId: data.contactListId ?? undefined,
        createdById: data.createdById,
      },
    });
  }

  async findById(id: string): Promise<Campaign | null> {
    return prisma.campaign.findUnique({
      where: { id },
    });
  }

  async findByIdWithSender(id: string): Promise<CampaignWithSender | null> {
    return prisma.campaign.findUnique({
      where: { id },
      include: {
        sender: { include: { domain: true } },
        contactList: { select: { id: true, name: true } },
      },
    });
  }

  async findByIdWithLogsAndSender(id: string): Promise<CampaignWithLogsAndSender | null> {
    return prisma.campaign.findUnique({
      where: { id },
      include: {
        sender: { select: { id: true, name: true, fromEmail: true } },
        contactList: { select: { id: true, name: true } },
        logs: {
          include: { contact: { select: { id: true, email: true, name: true } } },
          orderBy: { updatedAt: "desc" },
        },
      },
    });
  }

  async findByUserId(userId: string): Promise<CampaignWithSenderName[]> {
    return prisma.campaign.findMany({
      where: { createdById: userId },
      include: { sender: { select: { name: true } } },
      orderBy: { createdAt: "desc" },
    });
  }

  async searchByUserId(userId: string, query: string, limit: number): Promise<CampaignWithSenderName[]> {
    return prisma.campaign.findMany({
      where: {
        createdById: userId,
        OR: [
          { title: { contains: query, mode: "insensitive" } },
          { subject: { contains: query, mode: "insensitive" } },
        ],
      },
      include: { sender: { select: { name: true } } },
      orderBy: { createdAt: "desc" },
      take: limit,
    });
  }

  async update(id: string, data: UpdateCampaignDTO): Promise<Campaign> {
    return prisma.campaign.update({
      where: { id },
      data: {
        ...(data.title && { title: data.title }),
        ...(data.subject && { subject: data.subject }),
        ...(data.senderId && { senderId: data.senderId }),
        ...(data.contactListId !== undefined && { contactListId: data.contactListId }),
      },
    });
  }

  async updateStatus(id: string, status: CampaignStatus): Promise<Campaign> {
    return prisma.campaign.update({
      where: { id },
      data: { status },
    });
  }
}
