import { Domain, Sender } from "@prisma/client";
import { prisma } from "@/shared/infra/prisma/prisma-client";
import { CreateSenderDTO } from "../dtos/create-sender-dto";
import { UpdateSenderDTO } from "../dtos/update-sender-dto";
import { PublicSender, SendersRepository } from "./senders-repository";

const publicSelect = {
  id: true,
  name: true,
  fromEmail: true,
  provider: true,
  smtpHost: true,
  smtpPort: true,
  smtpUser: true,
  domainId: true,
  domain: { select: { id: true, domain: true, verificationStatus: true } },
} as const;

export class PrismaSendersRepository implements SendersRepository {
  async findById(id: string): Promise<Sender | null> {
    return prisma.sender.findUnique({
      where: { id },
    });
  }

  async findByIdWithDomain(id: string): Promise<(Sender & { domain: Domain | null }) | null> {
    return prisma.sender.findUnique({
      where: { id },
      include: { domain: true },
    });
  }

  async findByUserId(userId: string): Promise<PublicSender[]> {
    return prisma.sender.findMany({
      where: { userId },
      select: publicSelect,
      orderBy: { name: "asc" },
    });
  }

  async searchByUserId(userId: string, query: string, limit: number): Promise<PublicSender[]> {
    return prisma.sender.findMany({
      where: {
        userId,
        OR: [
          { name: { contains: query, mode: "insensitive" } },
          { fromEmail: { contains: query, mode: "insensitive" } },
        ],
      },
      select: publicSelect,
      take: limit,
    });
  }

  async findFirstByUserId(userId: string): Promise<Sender | null> {
    return prisma.sender.findFirst({
      where: { userId },
    });
  }

  async create(data: CreateSenderDTO & { encryptedPass?: string }): Promise<PublicSender> {
    return prisma.sender.create({
      data: {
        name: data.name,
        fromEmail: data.fromEmail,
        provider: data.provider,
        smtpHost: data.smtpHost,
        smtpPort: data.smtpPort,
        smtpUser: data.smtpUser,
        smtpPass: data.encryptedPass,
        domainId: data.domainId,
        userId: data.userId,
      },
      select: publicSelect,
    });
  }

  async update(
    id: string,
    data: Omit<UpdateSenderDTO, "smtpPass"> & { encryptedPass?: string }
  ): Promise<PublicSender> {
    return prisma.sender.update({
      where: { id },
      data: {
        name: data.name,
        fromEmail: data.fromEmail,
        provider: data.provider,
        smtpHost: data.smtpHost ?? null,
        smtpPort: data.smtpPort ?? null,
        smtpUser: data.smtpUser ?? null,
        ...(data.encryptedPass !== undefined && { smtpPass: data.encryptedPass }),
        domainId: data.domainId ?? null,
      },
      select: publicSelect,
    });
  }

  async delete(id: string): Promise<void> {
    await prisma.sender.delete({
      where: { id },
    });
  }
}
