import { Campaign, CampaignStatus, SenderProvider } from "@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 InMemoryCampaignsRepository implements CampaignsRepository {
  public items: Campaign[] = [];

  async create(data: CreateCampaignDTO): Promise<Campaign> {
    const campaign: Campaign = {
      id: `campaign-${this.items.length + 1}`,
      title: data.title,
      subject: data.subject,
      htmlBody: data.htmlBody,
      status: CampaignStatus.DRAFT,
      senderId: data.senderId ?? "sender-1",
      contactListId: data.contactListId ?? null,
      createdById: data.createdById,
      createdAt: new Date(),
      updatedAt: new Date(),
    };

    this.items.push(campaign);
    return campaign;
  }

  async findById(id: string): Promise<Campaign | null> {
    const campaign = this.items.find((item) => item.id === id);
    return campaign ?? null;
  }

  async findByIdWithSender(id: string): Promise<CampaignWithSender | null> {
    const campaign = this.items.find((item) => item.id === id);
    if (!campaign) return null;

    return {
      ...campaign,
      sender: {
        id: campaign.senderId,
        name: "Sender Test",
        fromEmail: "sender@example.com",
        provider: SenderProvider.SMTP,
        smtpHost: "smtp.example.com",
        smtpPort: 587,
        smtpUser: "sender@example.com",
        smtpPass: "encrypted-pass",
        domainId: null,
        domain: null,
        userId: campaign.createdById,
        createdAt: new Date(),
        updatedAt: new Date(),
      },
      contactList: null,
    };
  }

  async findByIdWithLogsAndSender(id: string): Promise<CampaignWithLogsAndSender | null> {
    const campaign = this.items.find((item) => item.id === id);
    if (!campaign) return null;

    return {
      ...campaign,
      sender: {
        id: campaign.senderId,
        name: "Sender Test",
        fromEmail: "sender@example.com",
      },
      contactList: null,
      logs: [],
    };
  }

  async findByUserId(userId: string): Promise<CampaignWithSenderName[]> {
    return this.items
      .filter((item) => item.createdById === userId)
      .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
      .map((item) => ({ ...item, sender: { name: "Sender Test" } }));
  }

  async searchByUserId(userId: string, query: string, limit: number): Promise<CampaignWithSenderName[]> {
    const normalized = query.toLowerCase();

    return this.items
      .filter(
        (item) =>
          item.createdById === userId &&
          (item.title.toLowerCase().includes(normalized) || item.subject.toLowerCase().includes(normalized))
      )
      .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
      .slice(0, limit)
      .map((item) => ({ ...item, sender: { name: "Sender Test" } }));
  }

  async update(id: string, data: UpdateCampaignDTO): Promise<Campaign> {
    const index = this.items.findIndex((item) => item.id === id);
    if (index === -1) {
      throw new Error("Campaign not found");
    }

    const current = this.items[index];
    const updated: Campaign = {
      ...current,
      ...(data.title && { title: data.title }),
      ...(data.subject && { subject: data.subject }),
      ...(data.senderId && { senderId: data.senderId }),
      ...(data.contactListId !== undefined && { contactListId: data.contactListId }),
      updatedAt: new Date(),
    };

    this.items[index] = updated;
    return updated;
  }

  async updateStatus(id: string, status: CampaignStatus): Promise<Campaign> {
    const index = this.items.findIndex((item) => item.id === id);
    if (index === -1) {
      throw new Error("Campaign not found");
    }

    const updated: Campaign = { ...this.items[index], status, updatedAt: new Date() };
    this.items[index] = updated;
    return updated;
  }
}
