import { OrderStatus } from "@prisma/client";
import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";
import ar from "../../../messages/ar.json";
import { db } from "@/lib/db";
import { carrierShipmentService } from "@/server/carriers";
import { canTransition, transitionOrder } from "@/server/domain/transitions";
import { generateLabelPdf } from "@/server/labels/pdf";
import { emitDashboardEvent } from "@/server/n8n";

export const dynamic = "force-dynamic";

async function findValidOrder(token: string) {
  return db.order.findFirst({
    where: { confirmationToken: token, tokenExpiresAt: { gt: new Date() } },
    include: { customer: true, items: true },
  });
}

async function confirmOrder(token: string) {
  "use server";
  const order = await findValidOrder(token);
  if (!order) redirect(`/c/${token}?result=expired`);
  try {
    const result = await transitionOrder(
      db,
      { orderId: order.id, to: OrderStatus.CONFIRMED, actor: "customer" },
      {
        shipments: carrierShipmentService,
        onConfirmed: async (confirmed) => {
          void generateLabelPdf(confirmed.id).catch((error) => console.error("Label generation failed", error));
        },
      },
    );
    void emitDashboardEvent({
      event: "ORDER_STATUS_CHANGED",
      orderId: order.id,
      actor: "customer",
      data: { from: order.status, to: result.order.status },
    });
  } catch (error) {
    console.error(error);
    redirect(`/c/${token}?result=unavailable`);
  }
  revalidatePath(`/c/${token}`);
  redirect(`/c/${token}?result=confirmed`);
}

async function cancelOrder(token: string) {
  "use server";
  const order = await findValidOrder(token);
  if (!order) redirect(`/c/${token}?result=expired`);
  try {
    const result = await transitionOrder(
      db,
      { orderId: order.id, to: OrderStatus.CANCELLED, actor: "customer", reason: "customer_request" },
      { shipments: carrierShipmentService },
    );
    void emitDashboardEvent({
      event: "ORDER_STATUS_CHANGED",
      orderId: order.id,
      actor: "customer",
      data: { from: order.status, to: result.order.status },
    });
  } catch (error) {
    console.error(error);
    redirect(`/c/${token}?result=unavailable`);
  }
  revalidatePath(`/c/${token}`);
  redirect(`/c/${token}?result=cancelled`);
}

async function changeAddress(token: string, formData: FormData) {
  "use server";
  const order = await findValidOrder(token);
  if (!order) redirect(`/c/${token}?result=expired`);
  const addressLine = String(formData.get("addressLine") ?? "").trim();
  if (addressLine.length < 10) redirect(`/c/${token}?result=unavailable`);

  await db.$transaction([
    db.order.update({ where: { id: order.id }, data: { addressRaw: addressLine, addressLine } }),
    db.orderEvent.create({
      data: {
        orderId: order.id,
        type: "ADDRESS_UPDATED",
        actor: "customer",
        message: "Customer submitted a new address",
        meta: { addressLine },
      },
    }),
  ]);
  void emitDashboardEvent({
    event: "ADDRESS_UPDATED",
    orderId: order.id,
    actor: "customer",
    data: { addressLine },
  });
  revalidatePath(`/c/${token}`);
  redirect(`/c/${token}?result=addressUpdated`);
}

const resultMessages: Record<string, string> = {
  confirmed: ar.confirmation.confirmed,
  cancelled: ar.confirmation.cancelled,
  addressUpdated: ar.confirmation.addressUpdated,
  unavailable: ar.confirmation.unavailable,
  expired: ar.confirmation.expired,
};

export default async function ConfirmationPage({
  params,
  searchParams,
}: {
  params: Promise<{ token: string }>;
  searchParams: Promise<{ result?: string }>;
}) {
  const [{ token }, query] = await Promise.all([params, searchParams]);
  const order = await findValidOrder(token);
  if (!order) {
    return (
      <main className="mx-auto flex min-h-screen max-w-lg items-center p-5">
        <section className="w-full rounded-2xl border border-red-900 bg-slate-900 p-7 text-center text-red-200">
          {ar.confirmation.expired}
        </section>
      </main>
    );
  }

  const telegramUsername = process.env.TELEGRAM_BOT_USERNAME;
  const telegramLink = telegramUsername
    ? `https://t.me/${telegramUsername}?start=${encodeURIComponent(token)}`
    : null;
  const resultMessage = query.result ? resultMessages[query.result] : undefined;
  const canConfirm = canTransition(order.status, OrderStatus.CONFIRMED);
  const canCancel = canTransition(order.status, OrderStatus.CANCELLED);
  const canChangeAddress = new Set<OrderStatus>([
    OrderStatus.NEW,
    OrderStatus.PENDING_CONFIRMATION,
    OrderStatus.NEEDS_REVIEW,
  ]).has(order.status);

  return (
    <main className="mx-auto min-h-screen max-w-xl p-4 sm:p-8">
      <section className="rounded-2xl border border-slate-800 bg-slate-900 p-6 shadow-2xl">
        <p className="text-sm font-bold text-cyan-400">{process.env.STORE_NAME ?? "Smart COD"}</p>
        <h1 className="mt-2 text-2xl font-bold">{ar.confirmation.title}</h1>
        {resultMessage ? <p className="mt-4 rounded-xl bg-slate-800 p-3 text-emerald-300">{resultMessage}</p> : null}
        <dl className="mt-6 grid gap-3 text-sm">
          <div><dt className="text-slate-400">{ar.confirmation.order}</dt><dd dir="ltr" className="font-mono">{order.id}</dd></div>
          <div><dt className="text-slate-400">{ar.confirmation.customer}</dt><dd>{order.customer.name}</dd></div>
          <div><dt className="text-slate-400">{ar.confirmation.address}</dt><dd>{[order.addressLine, order.city, order.governorate].filter(Boolean).join(" — ")}</dd></div>
          <div><dt className="text-slate-400">{ar.confirmation.items}</dt><dd>{order.items.map((item) => `${item.name} × ${item.qty}`).join(" • ")}</dd></div>
          <div><dt className="text-slate-400">{ar.confirmation.total}</dt><dd className="text-xl font-bold text-emerald-400">{order.codAmount.toFixed(2)} {order.currency}</dd></div>
        </dl>

        {canConfirm || canCancel ? (
          <div className="mt-7 grid gap-3 sm:grid-cols-2">
            {canConfirm ? <form action={confirmOrder.bind(null, token)}>
              <button className="w-full rounded-xl bg-emerald-600 px-4 py-3 font-bold text-white" type="submit">{ar.confirmation.confirm}</button>
            </form> : null}
            {canCancel ? <form action={cancelOrder.bind(null, token)}>
              <button className="w-full rounded-xl bg-red-600 px-4 py-3 font-bold text-white" type="submit">{ar.confirmation.cancel}</button>
            </form> : null}
          </div>
        ) : null}

        {canChangeAddress ? (
          <details className="mt-5 rounded-xl border border-slate-700 p-4">
            <summary className="cursor-pointer font-bold">{ar.confirmation.changeAddress}</summary>
            <form action={changeAddress.bind(null, token)} className="mt-4 grid gap-3">
              <textarea className="min-h-28 rounded-lg border border-slate-700 bg-slate-950 p-3" name="addressLine" placeholder={ar.confirmation.newAddress} required minLength={10} />
              <button className="rounded-lg bg-blue-600 px-4 py-2 font-bold" type="submit">{ar.confirmation.saveAddress}</button>
            </form>
          </details>
        ) : null}

        {telegramLink ? <a className="mt-5 block text-center text-cyan-400 underline" href={telegramLink}>{ar.confirmation.telegram}</a> : null}
      </section>
    </main>
  );
}
