"use server";

import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { writeFile, mkdir } from "fs/promises";
import path from "path";
import crypto from "crypto";
import { prisma } from "@/lib/prisma";
import { getClient as getResendClient } from "@/lib/resend";
import { SITE } from "@/lib/site";
import { requirePermission } from "@/lib/permissions";

const BASE = "/iv-manage-84x2/marketing";
const ALLOWED_IMAGE_TYPES: Record<string, string> = {
  "image/jpeg": "jpg",
  "image/png": "png",
  "image/webp": "webp",
  "image/gif": "gif",
};
const MAX_IMAGE_SIZE = 5 * 1024 * 1024;

function revalidateAll() {
  revalidatePath(BASE);
  revalidatePath(`${BASE}/sections`);
  revalidatePath(`${BASE}/featured`);
  revalidatePath(`${BASE}/best-sellers`);
  revalidatePath(`${BASE}/new-arrivals`);
  revalidatePath(`${BASE}/flash-sale`);
  revalidatePath(`${BASE}/campaigns`);
  revalidatePath(`${BASE}/abandoned-cart`);
  revalidatePath("/");
}

// ---------- Banners ----------

const ALLOWED_DEVICES = new Set(["desktop", "mobile", "both"]);

export async function createBanner(formData: FormData) {
  await requirePermission("marketing", "add");
  const title = String(formData.get("title") ?? "").trim() || null;
  const link = String(formData.get("link") ?? "").trim() || null;
  const deviceRaw = String(formData.get("device") ?? "both");
  const device = ALLOWED_DEVICES.has(deviceRaw) ? deviceRaw : "both";
  const file = formData.get("image");

  if (!(file instanceof File) || file.size === 0) redirect(`${BASE}?error=Pick+an+image`);
  const ext = ALLOWED_IMAGE_TYPES[file.type];
  if (!ext) redirect(`${BASE}?error=Only+JPG%2C+PNG%2C+WEBP%2C+or+GIF+images+are+allowed`);
  if (file.size > MAX_IMAGE_SIZE) redirect(`${BASE}?error=Image+must+be+under+5MB`);

  const uploadDir = path.join(process.cwd(), "public", "uploads", "banners");
  await mkdir(uploadDir, { recursive: true });
  const filename = `${crypto.randomUUID()}.${ext}`;
  const bytes = Buffer.from(await file.arrayBuffer());
  await writeFile(path.join(uploadDir, filename), bytes);

  const count = await prisma.banner.count({ where: { device } });
  await prisma.banner.create({
    data: { image: `/uploads/banners/${filename}`, title, link, device, sortOrder: count },
  });
  revalidateAll();
  redirect(`${BASE}?success=Banner+added.`);
}

export async function toggleBanner(id: string) {
  await requirePermission("marketing", "edit");
  const banner = await prisma.banner.findUniqueOrThrow({ where: { id } });
  await prisma.banner.update({ where: { id }, data: { active: !banner.active } });
  revalidateAll();
  redirect(`${BASE}?success=Banner+updated.`);
}

export async function updateBannerSortOrder(id: string, formData: FormData) {
  await requirePermission("marketing", "edit");
  const sortOrder = Math.max(0, Math.round(Number(formData.get("sortOrder") ?? 0)));
  await prisma.banner.update({ where: { id }, data: { sortOrder } });
  revalidateAll();
  redirect(`${BASE}?success=Sort+order+updated.`);
}

export async function deleteBanner(id: string) {
  await requirePermission("marketing", "delete");
  await prisma.banner.delete({ where: { id } });
  revalidateAll();
  redirect(`${BASE}?success=Banner+deleted.`);
}

// ---------- Homepage Sections ----------

export async function updateHomepageSection(id: string, formData: FormData) {
  await requirePermission("marketing", "edit");
  const active = formData.get("active") === "on";
  const sortOrder = Math.max(0, Math.round(Number(formData.get("sortOrder") ?? 0)));
  const itemLimit = Math.max(1, Math.round(Number(formData.get("itemLimit") ?? 8)));
  await prisma.homepageSection.update({ where: { id }, data: { active, sortOrder, itemLimit } });
  revalidateAll();
  redirect(`${BASE}/sections?success=Section+updated.`);
}

// ---------- Featured Products ----------

export async function toggleFeatured(productId: string) {
  await requirePermission("marketing", "edit");
  const product = await prisma.product.findUniqueOrThrow({ where: { id: productId } });
  await prisma.product.update({ where: { id: productId }, data: { featured: !product.featured } });
  revalidateAll();
  redirect(`${BASE}/featured?success=Featured+status+updated.`);
}

// ---------- Flash Sale ----------

export async function setHomepageFlashSale(id: string) {
  await requirePermission("marketing", "edit");
  await prisma.$transaction([
    prisma.festivalOffer.updateMany({ data: { showOnHomepage: false } }),
    prisma.festivalOffer.update({ where: { id }, data: { showOnHomepage: true } }),
  ]);
  revalidateAll();
  redirect(`${BASE}/flash-sale?success=Flash+sale+set.`);
}

export async function clearHomepageFlashSale() {
  await requirePermission("marketing", "edit");
  await prisma.festivalOffer.updateMany({ data: { showOnHomepage: false } });
  revalidateAll();
  redirect(`${BASE}/flash-sale?success=Flash+sale+cleared.`);
}

// ---------- Email Campaigns ----------

export async function sendEmailCampaign(formData: FormData) {
  await requirePermission("marketing", "approve");
  const subject = String(formData.get("subject") ?? "").trim();
  const body = String(formData.get("body") ?? "").trim();
  const audience = String(formData.get("audience") ?? "all");
  const manualEmailsRaw = String(formData.get("manualEmails") ?? "").trim();

  if (!subject || !body) redirect(`${BASE}/campaigns?error=Subject+and+message+are+required`);

  let recipients: string[] = [];
  if (audience === "manual") {
    recipients = manualEmailsRaw
      .split(/[\n,]/)
      .map((e) => e.trim())
      .filter((e) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e));
  } else if (audience === "all") {
    const customers = await prisma.customer.findMany({ where: { blocked: false }, select: { email: true } });
    recipients = customers.map((c) => c.email);
  } else {
    // a CustomerGroup id
    const customers = await prisma.customer.findMany({ where: { groupId: audience, blocked: false }, select: { email: true } });
    recipients = customers.map((c) => c.email);
  }

  recipients = [...new Set(recipients)];
  if (recipients.length === 0) redirect(`${BASE}/campaigns?error=No+recipients+matched+that+audience`);

  const from = process.env.EMAIL_FROM || `${SITE.name} <onboarding@resend.dev>`;
  const resend = getResendClient();
  let sentCount = 0;
  for (const to of recipients) {
    try {
      await resend.emails.send({
        from,
        to,
        subject,
        html: `<div style="font-family: Arial, sans-serif; max-width: 480px; margin: 0 auto; padding: 24px; white-space: pre-line;">${body}</div>`,
      });
      sentCount++;
    } catch {
      // keep going — one bad address shouldn't kill the whole campaign
    }
  }

  await prisma.emailCampaign.create({
    data: {
      subject,
      body,
      audience,
      manualEmails: audience === "manual" ? manualEmailsRaw : null,
      status: "sent",
      sentCount,
      sentAt: new Date(),
    },
  });

  revalidateAll();
  redirect(`${BASE}/campaigns?success=Campaign+sent.`);
}
