"use server";

import { revalidatePath } from "next/cache";
import { eq } from "drizzle-orm";
import { z } from "zod";
import { db } from "@/lib/db/client";
import { storeOrders } from "@/lib/db/schema";
import { requireAdmin } from "@/lib/auth/admin-guard";
import { logAdminAction } from "@/lib/audit";
import { sendTemplatedEmail } from "@/lib/email/send";
import { loadEnv } from "@/lib/env";

const statusValues = [
  "pending_invoice",
  "invoiced",
  "paid",
  "shipped",
  "delivered",
  "cancelled",
] as const;

const STATUS_LABELS: Record<(typeof statusValues)[number], string> = {
  pending_invoice: "Pending invoice",
  invoiced: "Invoice sent",
  paid: "Paid",
  shipped: "Shipped",
  delivered: "Delivered",
  cancelled: "Cancelled",
};

async function ensureAdmin() {
  const session = await requireAdmin();
  return (session.user as { id?: string }).id!;
}

const updateOrderSchema = z.object({
  id: z.string().uuid(),
  status: z.enum(statusValues),
  invoiceUrl: z.string().max(500).optional().default(""),
  trackingUrl: z.string().max(500).optional().default(""),
  trackingNumber: z.string().max(100).optional().default(""),
  adminNotes: z.string().max(2000).optional().default(""),
});

/**
 * Update an order's workflow status. Sets the matching timestamp column
 * automatically so the audit trail of when each state was reached is kept
 * with the order itself. Sends a status update email to the customer.
 */
export async function updateOrder(formData: FormData) {
  const adminId = await ensureAdmin();
  const parsed = updateOrderSchema.parse({
    id: formData.get("id"),
    status: formData.get("status"),
    invoiceUrl: formData.get("invoiceUrl") ?? "",
    trackingUrl: formData.get("trackingUrl") ?? "",
    trackingNumber: formData.get("trackingNumber") ?? "",
    adminNotes: formData.get("adminNotes") ?? "",
  });

  const [prev] = await db
    .select()
    .from(storeOrders)
    .where(eq(storeOrders.id, parsed.id))
    .limit(1);
  if (!prev) throw new Error("Order not found");

  const now = new Date();
  type Patch = {
    status: typeof parsed.status;
    invoiceUrl: string | null;
    trackingUrl: string | null;
    trackingNumber: string | null;
    adminNotes: string;
    updatedAt: Date;
    invoicedAt?: Date | null;
    paidAt?: Date | null;
    shippedAt?: Date | null;
    deliveredAt?: Date | null;
    cancelledAt?: Date | null;
  };
  const patch: Patch = {
    status: parsed.status,
    invoiceUrl: parsed.invoiceUrl || null,
    trackingUrl: parsed.trackingUrl || null,
    trackingNumber: parsed.trackingNumber || null,
    adminNotes: parsed.adminNotes,
    updatedAt: now,
  };

  // Stamp the first time the order hits each state.
  if (parsed.status === "invoiced" && !prev.invoicedAt) patch.invoicedAt = now;
  if (parsed.status === "paid" && !prev.paidAt) patch.paidAt = now;
  if (parsed.status === "shipped" && !prev.shippedAt) patch.shippedAt = now;
  if (parsed.status === "delivered" && !prev.deliveredAt)
    patch.deliveredAt = now;
  if (parsed.status === "cancelled" && !prev.cancelledAt)
    patch.cancelledAt = now;

  await db
    .update(storeOrders)
    .set(patch)
    .where(eq(storeOrders.id, parsed.id));

  await logAdminAction({
    adminUserId: adminId,
    action: `store_order_${parsed.status}`,
    targetId: parsed.id,
  });

  // Email the customer when the status materially changed.
  if (parsed.status !== prev.status) {
    const env = loadEnv();
    const statusLabel = STATUS_LABELS[parsed.status];
    const statusBlock = buildStatusBlock(parsed.status, {
      invoiceUrl: parsed.invoiceUrl,
      trackingUrl: parsed.trackingUrl,
      trackingNumber: parsed.trackingNumber,
    });
    try {
      await sendTemplatedEmail({
        to: prev.customerEmail,
        templateSlug: "store-order-status-changed",
        variables: {
          name: prev.customerName,
          orderNumber: prev.orderNumber,
          statusLabel,
          statusBlock,
          orderUrl: `${env.nextAuthUrl}/products/store/orders/${prev.id}`,
        },
      });
    } catch (err) {
      console.error("[store-order] status email failed", err);
    }
  }

  revalidatePath("/admin/store/orders");
  revalidatePath(`/admin/store/orders/${parsed.id}`);
  revalidatePath(`/products/store/orders/${parsed.id}`);
  revalidatePath("/account/orders");
}

function buildStatusBlock(
  status: (typeof statusValues)[number],
  extras: {
    invoiceUrl?: string;
    trackingUrl?: string;
    trackingNumber?: string;
  },
): string {
  const lines: string[] = [];
  switch (status) {
    case "invoiced":
      lines.push(
        "Your invoice has been issued. Payment instructions are attached to the invoice.",
      );
      if (extras.invoiceUrl) lines.push(`Invoice: ${extras.invoiceUrl}`);
      break;
    case "paid":
      lines.push("Payment received — thank you. We'll ship shortly.");
      break;
    case "shipped":
      lines.push("Your order has shipped.");
      if (extras.trackingNumber)
        lines.push(`Tracking reference: ${extras.trackingNumber}`);
      if (extras.trackingUrl) lines.push(`Track: ${extras.trackingUrl}`);
      break;
    case "delivered":
      lines.push(
        "Marked as delivered. If anything's off, reply to this email and we'll sort it.",
      );
      break;
    case "cancelled":
      lines.push(
        "Your order has been cancelled. If this was unexpected, please contact us.",
      );
      break;
    default:
      lines.push(STATUS_LABELS[status]);
  }
  return lines.join("\n");
}
