import { prisma } from "@/lib/prisma";
import type { SectorEmailsUpdateInput } from "@/validators/sector-emails";

function normalizeEmails(emails: string[]) {
  return [
    ...new Set(
      emails.map((email) => email.trim().toLowerCase()).filter(Boolean),
    ),
  ].sort((left, right) => left.localeCompare(right));
}

function mapSectorEmailSetting(sector: {
  id: number;
  secteurs: string | null;
  destinataires: { email: string }[];
}) {
  return {
    id: sector.id,
    name: sector.secteurs?.trim() || `Secteur ${sector.id}`,
    emails: normalizeEmails(
      sector.destinataires.map((recipient) => recipient.email),
    ),
  };
}

export async function getSectorEmailSettingById(id: number) {
  const sector = await prisma.secteurs_travail.findFirst({
    where: {
      id,
      actif: true,
    },
    select: {
      id: true,
      secteurs: true,
      destinataires: {
        where: {
          actif: true,
        },
        orderBy: {
          email: "asc",
        },
        select: {
          email: true,
        },
      },
    },
  });

  return sector ? mapSectorEmailSetting(sector) : null;
}

export async function getSectorEmailsSettings() {
  const [sectors, employees] = await Promise.all([
    prisma.secteurs_travail.findMany({
      where: {
        actif: true,
      },
      orderBy: {
        id: "asc",
      },
      select: {
        id: true,
        secteurs: true,
        destinataires: {
          where: {
            actif: true,
          },
          orderBy: {
            email: "asc",
          },
          select: {
            email: true,
          },
        },
      },
    }),
    prisma.employes.findMany({
      where: {
        EmailE2e: {
          not: null,
        },
      },
      orderBy: [
        {
          NSA: "asc",
        },
        {
          PRE: "asc",
        },
      ],
      select: {
        COS: true,
        NSA: true,
        PRE: true,
        EmailE2e: true,
        Actif: true,
      },
    }),
  ]);

  const seenEmails = new Set<string>();
  const recipients = employees.flatMap((employee) => {
    const email = employee.EmailE2e?.trim().toLowerCase();

    if (!email || seenEmails.has(email)) {
      return [];
    }

    seenEmails.add(email);

    return [
      {
        cos: employee.COS,
        nom: employee.NSA?.trim() ?? "",
        prenom: employee.PRE?.trim() ?? "",
        email,
        actif: employee.Actif ?? false,
      },
    ];
  });

  return {
    sectors: sectors.map(mapSectorEmailSetting),
    recipients,
  };
}

export async function updateSectorEmails(data: SectorEmailsUpdateInput) {
  const existingSector = await prisma.secteurs_travail.findFirst({
    where: {
      id: data.sectorId,
      actif: true,
    },
    select: {
      id: true,
    },
  });

  if (!existingSector) {
    return null;
  }

  const emails = normalizeEmails(data.emails);

  await prisma.$transaction(async (transaction) => {
    await transaction.secteurs_travail_destinataires.updateMany({
      where: {
        secteur_id: data.sectorId,
      },
      data: {
        actif: false,
      },
    });

    if (emails.length === 0) {
      return;
    }

    await transaction.secteurs_travail_destinataires.createMany({
      data: emails.map((email) => ({
        secteur_id: data.sectorId,
        email,
        actif: true,
      })),
      skipDuplicates: true,
    });

    await transaction.secteurs_travail_destinataires.updateMany({
      where: {
        secteur_id: data.sectorId,
        email: {
          in: emails,
        },
      },
      data: {
        actif: true,
      },
    });
  });

  return getSectorEmailSettingById(data.sectorId);
}