"use server";

import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";
import { hasPermission } from "@/lib/adminAuth";
import { connectDB } from "@/lib/db";
import { GiftVoucher } from "@/models/GiftVoucher";
import { Settings } from "@/models/Settings";
import { getSettings } from "@/lib/settings";
import { getStripeClient, isStripeConfigured } from "@/lib/stripe";
import { generateUniqueVoucherCode, defaultVoucherExpiry } from "@/lib/vouchers";
import { sendVoucherCode, notifyAdminVoucherRequested, notifyPurchaserVoucherPending } from "@/lib/voucherEmails";

const VOUCHERS_ADMIN_PATH = "/de/admin/vouchers";
const MIN_AMOUNT = 20;
const MAX_AMOUNT = 1000;

type FormState = { error?: string; success?: boolean; manual?: boolean };

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

// Öffentliche Gutschein-Anfrage (/gutscheine). Legt immer erst einen
// unbezahlten Gutschein an — läuft Stripe, sofort zur Kasse weiterleiten;
// sonst meldet sich Rakku wegen der Zahlungsdetails, admin bestätigt die
// Zahlung später manuell im Admin-Bereich.
export async function requestVoucherAction(_prev: FormState, formData: FormData): Promise<FormState> {
  const amount = Math.round(Number(formData.get("amount")) * 100) / 100;
  const purchaserName = String(formData.get("purchaserName") || "").trim();
  const purchaserEmail = String(formData.get("purchaserEmail") || "").trim().toLowerCase();
  const recipientName = String(formData.get("recipientName") || "").trim();
  const message = String(formData.get("message") || "").trim();
  const locale = formData.get("locale") === "en" ? "en" : "de";

  const settings = await getSettings();
  if (settings.voucherSettings?.enabled === false) {
    return {
      error:
        locale === "en"
          ? "Voucher purchases are currently paused."
          : "Gutschein-Käufe sind aktuell pausiert.",
    };
  }

  if (!purchaserName) return { error: "Bitte einen Namen eingeben." };
  if (!EMAIL_RE.test(purchaserEmail)) return { error: "Bitte eine gültige E-Mail-Adresse eingeben." };
  if (!Number.isFinite(amount) || amount < MIN_AMOUNT || amount > MAX_AMOUNT) {
    return { error: `Bitte einen Betrag zwischen ${MIN_AMOUNT} € und ${MAX_AMOUNT} € wählen.` };
  }

  await connectDB();
  const voucher = await GiftVoucher.create({
    amount,
    purchaserName,
    purchaserEmail,
    recipientName,
    message,
    locale,
  });

  const stripe = getStripeClient();

  if (stripe && isStripeConfigured() && settings.paymentSettings?.enabled) {
    const baseUrl = process.env.SITE_URL;
    const session = await stripe.checkout.sessions.create({
      mode: "payment",
      line_items: [
        {
          price_data: {
            currency: "eur",
            unit_amount: Math.round(amount * 100),
            product_data: {
              name: "Geschenkgutschein — Rakku Photography",
              description: recipientName ? `Für ${recipientName}` : undefined,
            },
          },
          quantity: 1,
        },
      ],
      customer_email: purchaserEmail,
      metadata: { voucherId: String(voucher._id) },
      payment_intent_data: { metadata: { voucherId: String(voucher._id) } },
      success_url: `${baseUrl}/${locale}/gutscheine?success=1`,
      cancel_url: `${baseUrl}/${locale}/gutscheine?cancelled=1`,
    });
    voucher.stripeSessionId = session.id;
    await voucher.save();
    if (session.url) redirect(session.url);
    return { error: "Zahlung konnte nicht gestartet werden." };
  }

  const adminEmail = settings.invoiceSettings?.email || settings.socialLinks?.email;
  await Promise.all([
    notifyAdminVoucherRequested(adminEmail, { purchaserName, purchaserEmail, amount, message }),
    notifyPurchaserVoucherPending({ purchaserName, purchaserEmail, amount, locale }),
  ]);

  return { success: true, manual: true };
}

export async function adminIssueVoucherAction(_prev: FormState, formData: FormData): Promise<FormState> {
  if (!(await hasPermission("vouchers_create"))) return { error: "Keine Berechtigung." };
  const amount = Math.round(Number(formData.get("amount")) * 100) / 100;
  const purchaserName = String(formData.get("purchaserName") || "").trim();
  const purchaserEmail = String(formData.get("purchaserEmail") || "").trim().toLowerCase();
  const recipientName = String(formData.get("recipientName") || "").trim();
  const message = String(formData.get("message") || "").trim();
  const sendEmail = formData.get("sendEmail") === "on";

  if (!purchaserName) return { error: "Bitte einen Namen eingeben." };
  if (!EMAIL_RE.test(purchaserEmail)) return { error: "Bitte eine gültige E-Mail-Adresse eingeben." };
  if (!Number.isFinite(amount) || amount <= 0) return { error: "Bitte einen gültigen Betrag eingeben." };

  await connectDB();
  const code = await generateUniqueVoucherCode();
  const now = new Date();
  await GiftVoucher.create({
    code,
    amount,
    purchaserName,
    purchaserEmail,
    recipientName,
    message,
    paid: true,
    paidAt: now,
    paymentMethod: "manual",
    expiresAt: defaultVoucherExpiry(now),
  });

  if (sendEmail) {
    // Manuell im Admin ausgestellt (z. B. Bar-/Vor-Ort-Verkauf) — kein
    // Anfrageformular mit Sprachkontext vorhanden, daher Standard Deutsch.
    await sendVoucherCode({ purchaserName, purchaserEmail, recipientName, amount, code, locale: "de" });
  }

  revalidatePath(VOUCHERS_ADMIN_PATH);
  return { success: true };
}

type BulkFormState = { error?: string; codes?: string[] };

// Mehrere Gutscheine auf einmal, ohne einzelne Käufer-Angaben — z. B. für
// eine Convention-Verlosung. Alle mit demselben Betrag, sofort als bezahlt
// markiert (kein echter Zahlungseingang bei einer Verlosung).
export async function adminBulkIssueVouchersAction(_prev: BulkFormState, formData: FormData): Promise<BulkFormState> {
  if (!(await hasPermission("vouchers_create"))) return { error: "Keine Berechtigung." };
  const count = Math.round(Number(formData.get("count")));
  const amount = Math.round(Number(formData.get("amount")) * 100) / 100;
  const label = String(formData.get("label") || "").trim();

  if (!label) return { error: "Bitte eine Bezeichnung eingeben, z. B. Convention-Verlosung 2026." };
  if (!Number.isFinite(count) || count < 1 || count > 200) return { error: "Bitte eine Anzahl zwischen 1 und 200 eingeben." };
  if (!Number.isFinite(amount) || amount <= 0) return { error: "Bitte einen gültigen Betrag eingeben." };

  await connectDB();
  const now = new Date();
  const codes: string[] = [];
  for (let i = 0; i < count; i++) {
    const code = await generateUniqueVoucherCode();
    await GiftVoucher.create({
      code,
      amount,
      purchaserName: label,
      purchaserEmail: "",
      paid: true,
      paidAt: now,
      paymentMethod: "manual",
      expiresAt: defaultVoucherExpiry(now),
    });
    codes.push(code);
  }

  revalidatePath(VOUCHERS_ADMIN_PATH);
  return { codes };
}

// Admin-Schalter: neue Gutschein-Käufe auf /gutscheine sperren/freigeben.
// Bestehende Gutscheine sind davon nicht betroffen.
export async function setVoucherPurchasesEnabledAction(enabled: boolean) {
  if (!(await hasPermission("settings"))) return;
  await connectDB();
  await Settings.findOneAndUpdate(
    { key: "main" },
    { $set: { "voucherSettings.enabled": enabled }, $setOnInsert: { key: "main" } },
    { upsert: true }
  );
  revalidatePath("/de/admin/settings");
  revalidatePath("/[locale]/gutscheine", "page");
}

export async function adminMarkVoucherPaidAction(voucherId: string) {
  if (!(await hasPermission("vouchers_edit"))) return;
  await connectDB();
  const voucher = await GiftVoucher.findById(voucherId);
  if (!voucher || voucher.paid) return;

  const code = await generateUniqueVoucherCode();
  voucher.code = code;
  voucher.paid = true;
  voucher.paidAt = new Date();
  voucher.paymentMethod = "manual";
  voucher.expiresAt = defaultVoucherExpiry();
  await voucher.save();

  await sendVoucherCode({
    purchaserName: voucher.purchaserName,
    purchaserEmail: voucher.purchaserEmail,
    recipientName: voucher.recipientName,
    amount: voucher.amount,
    code,
    locale: voucher.locale,
  });

  revalidatePath(VOUCHERS_ADMIN_PATH);
}

export async function adminCancelVoucherAction(voucherId: string) {
  if (!(await hasPermission("vouchers_edit"))) return;
  await connectDB();
  await GiftVoucher.findByIdAndUpdate(voucherId, { cancelled: true });
  revalidatePath(VOUCHERS_ADMIN_PATH);
}
