"use server";

import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";
import { hasPermission } from "@/lib/adminAuth";
import { connectDB } from "@/lib/db";
import { Service, SERVICE_STATUSES, type ServiceStatus } from "@/models/Service";
import { SHOOTING_TYPES, type ShootingType } from "@/lib/orderConstants";

const SERVICES_PATH = "/de/admin/services";

type FormState = { error?: string };

function readShootingType(formData: FormData): ShootingType {
  const raw = String(formData.get("shootingType") || "Other");
  return (SHOOTING_TYPES.includes(raw as ShootingType) ? raw : "Other") as ShootingType;
}

// Ein Zusatzoption pro Zeile, Format "Label | Preis" — bewusst kein
// dynamisches Wiederhol-Formular, damit die Pflege für eine Handvoll
// Zusatzoptionen pro Preisstufe einfach bleibt. DE/EN-Textarea werden
// zeilenweise nach Reihenfolge gepaart.
function parseAddOns(deText: string, enText: string) {
  const deLines = deText.split("\n").map((l) => l.trim()).filter(Boolean);
  const enLines = enText.split("\n").map((l) => l.trim()).filter(Boolean);
  return deLines
    .map((line, i) => {
      const [label, priceRaw] = line.split("|").map((s) => s.trim());
      const priceSurcharge = Number((priceRaw || "").replace(",", "."));
      if (!label || !Number.isFinite(priceSurcharge) || priceSurcharge < 0) return null;
      const enLine = enLines[i] || "";
      const labelEn = enLine.split("|")[0]?.trim() || "";
      return { label, labelEn, priceSurcharge };
    })
    .filter((a): a is { label: string; labelEn: string; priceSurcharge: number } => a !== null);
}

function readPromo(formData: FormData) {
  const promoPriceRaw = String(formData.get("promoPrice") || "").trim();
  const promoPrice = promoPriceRaw ? Number(promoPriceRaw) : null;
  const promoFromRaw = String(formData.get("promoFrom") || "").trim();
  const promoUntilRaw = String(formData.get("promoUntil") || "").trim();
  return {
    promoPrice: promoPrice !== null && Number.isFinite(promoPrice) && promoPrice >= 0 ? promoPrice : null,
    promoLabel: String(formData.get("promoLabel") || "").trim(),
    promoFrom: promoFromRaw ? new Date(promoFromRaw) : null,
    promoUntil: promoUntilRaw ? new Date(promoUntilRaw) : null,
  };
}

export async function createServiceAction(_prev: FormState, formData: FormData): Promise<FormState> {
  if (!(await hasPermission("services_create"))) return { error: "Nicht eingeloggt." };
  const title = String(formData.get("title") || "").trim();
  if (!title) return { error: "Bitte einen Titel eingeben." };

  await connectDB();
  await Service.create({
    title,
    titleEn: String(formData.get("titleEn") || "").trim(),
    description: String(formData.get("description") || "").trim(),
    descriptionEn: String(formData.get("descriptionEn") || "").trim(),
    shootingType: readShootingType(formData),
    status: "available",
    sortOrder: Date.now(),
    tiers: [],
  });
  revalidatePath(SERVICES_PATH);
  return {};
}

export async function updateServiceAction(_prev: FormState, formData: FormData): Promise<FormState> {
  if (!(await hasPermission("services_edit"))) return { error: "Nicht eingeloggt." };
  const id = String(formData.get("id") || "");
  const title = String(formData.get("title") || "").trim();
  if (!title) return { error: "Bitte einen Titel eingeben." };

  await connectDB();
  await Service.findByIdAndUpdate(id, {
    title,
    titleEn: String(formData.get("titleEn") || "").trim(),
    description: String(formData.get("description") || "").trim(),
    descriptionEn: String(formData.get("descriptionEn") || "").trim(),
    shootingType: readShootingType(formData),
  });
  revalidatePath(SERVICES_PATH);
  revalidatePath(`${SERVICES_PATH}/${id}/edit`);
  redirect(SERVICES_PATH);
}

export async function setServiceStatusAction(id: string, status: ServiceStatus) {
  if (!(await hasPermission("services_edit"))) return;
  if (!SERVICE_STATUSES.includes(status)) return;
  await connectDB();
  await Service.findByIdAndUpdate(id, { status });
  revalidatePath(SERVICES_PATH);
}

export async function deleteServiceAction(id: string) {
  if (!(await hasPermission("services_delete"))) return;
  await connectDB();
  await Service.findByIdAndDelete(id);
  revalidatePath(SERVICES_PATH);
}

// Preisstufen leben eingebettet im Service-Dokument (immer nur im Kontext
// ihres Angebots relevant, nie eigenständig abgefragt) — daher hier per
// Subdokument-Positionsoperator ($) statt eigener Collection.

export async function addTierAction(_prev: FormState, formData: FormData): Promise<FormState> {
  if (!(await hasPermission("services_create"))) return { error: "Nicht eingeloggt." };
  const serviceId = String(formData.get("serviceId") || "");
  const name = String(formData.get("name") || "").trim();
  const price = Number(formData.get("price"));
  if (!name) return { error: "Bitte einen Namen für die Preisstufe eingeben." };
  if (!Number.isFinite(price) || price < 0) return { error: "Bitte einen gültigen Preis eingeben." };

  await connectDB();
  await Service.findByIdAndUpdate(serviceId, {
    $push: {
      tiers: {
        name,
        nameEn: String(formData.get("nameEn") || "").trim(),
        price,
        addOns: parseAddOns(String(formData.get("addOns") || ""), String(formData.get("addOnsEn") || "")),
        priceFrom: formData.get("priceFrom") === "on",
        deliverables: String(formData.get("deliverables") || "").trim(),
        deliverablesEn: String(formData.get("deliverablesEn") || "").trim(),
        active: true,
        sortOrder: Date.now(),
        ...readPromo(formData),
      },
    },
  });
  revalidatePath(SERVICES_PATH);
  revalidatePath(`${SERVICES_PATH}/${serviceId}/edit`);
  return {};
}

export async function updateTierAction(serviceId: string, tierId: string, formData: FormData) {
  if (!(await hasPermission("services_edit"))) return;
  const name = String(formData.get("name") || "").trim();
  const price = Number(formData.get("price"));
  if (!name || !Number.isFinite(price) || price < 0) return;

  await connectDB();
  const promo = readPromo(formData);
  await Service.updateOne(
    { _id: serviceId, "tiers._id": tierId },
    {
      $set: {
        "tiers.$.name": name,
        "tiers.$.nameEn": String(formData.get("nameEn") || "").trim(),
        "tiers.$.price": price,
        "tiers.$.addOns": parseAddOns(String(formData.get("addOns") || ""), String(formData.get("addOnsEn") || "")),
        "tiers.$.priceFrom": formData.get("priceFrom") === "on",
        "tiers.$.deliverables": String(formData.get("deliverables") || "").trim(),
        "tiers.$.deliverablesEn": String(formData.get("deliverablesEn") || "").trim(),
        "tiers.$.promoPrice": promo.promoPrice,
        "tiers.$.promoLabel": promo.promoLabel,
        "tiers.$.promoFrom": promo.promoFrom,
        "tiers.$.promoUntil": promo.promoUntil,
      },
    }
  );
  revalidatePath(SERVICES_PATH);
  revalidatePath(`${SERVICES_PATH}/${serviceId}/edit`);
}

export async function setTierActiveAction(serviceId: string, tierId: string, active: boolean) {
  if (!(await hasPermission("services_edit"))) return;
  await connectDB();
  await Service.updateOne({ _id: serviceId, "tiers._id": tierId }, { $set: { "tiers.$.active": active } });
  revalidatePath(SERVICES_PATH);
  revalidatePath(`${SERVICES_PATH}/${serviceId}/edit`);
}

export async function deleteTierAction(serviceId: string, tierId: string) {
  if (!(await hasPermission("services_delete"))) return;
  await connectDB();
  await Service.findByIdAndUpdate(serviceId, { $pull: { tiers: { _id: tierId } } });
  revalidatePath(SERVICES_PATH);
  revalidatePath(`${SERVICES_PATH}/${serviceId}/edit`);
}
