import "server-only";

import { createAdminClient } from "@/lib/supabase/admin";
import { sendWhatsAppText } from "@/lib/whatsapp/sendNotification";

type NotificationEvent = {
  id: string;
  order_id: string;
  event_type: "order_created" | "payment_verified";
  channel: string;
  status: string;
  attempt_count: number;
  recipient: string | null;
};

function formatMoney(value: number | string | null | undefined) {
  return `₦${Number(value ?? 0).toLocaleString("en-NG")}`;
}

function readableFulfilmentStatus(status: string | null) {
  switch (status) {
    case "confirmed":
      return "Order Confirmed";

    case "preparing":
      return "Preparing Order";

    case "out_for_delivery":
      return "Out for Delivery";

    case "delivered":
      return "Delivered";

    case "cancelled":
      return "Cancelled";

    default:
      return "Awaiting Confirmation";
  }
}

function readablePaymentStatus(status: string | null) {
  switch (status) {
    case "paid":
      return "Paid";

    case "failed":
      return "Failed";

    default:
      return "Awaiting Payment";
  }
}

/**
 * Atomically claim one notification event.
 *
 * Only pending or failed notifications may be claimed.
 * This protects against two requests sending the same
 * WhatsApp notification at approximately the same time.
 */
async function claimNotification(eventId: string) {
  const supabase = createAdminClient();

  const { data: claimedEvent, error: claimError } =
    await supabase
      .from("notification_events")
      .update({
        status: "processing",
        updated_at: new Date().toISOString(),
      })
      .eq("id", eventId)
      .in("status", ["pending", "failed"])
      .select(
        `
          id,
          order_id,
          event_type,
          channel,
          status,
          attempt_count,
          recipient
        `
      )
      .maybeSingle();

  if (claimError) {
    throw new Error(claimError.message);
  }

  if (claimedEvent) {
    const nextAttempt =
      Number(claimedEvent.attempt_count ?? 0) + 1;

    const { error: attemptError } = await supabase
      .from("notification_events")
      .update({
        attempt_count: nextAttempt,
        last_error: null,
        updated_at: new Date().toISOString(),
      })
      .eq("id", claimedEvent.id)
      .eq("status", "processing");

    if (attemptError) {
      throw new Error(attemptError.message);
    }

    return {
      ...claimedEvent,
      attempt_count: nextAttempt,
    } as NotificationEvent;
  }

  /**
   * Nothing was claimed.
   * Find out why so that we can safely skip it.
   */
  const { data: existingEvent, error: existingError } =
    await supabase
      .from("notification_events")
      .select(
        `
          id,
          order_id,
          event_type,
          channel,
          status,
          attempt_count,
          recipient
        `
      )
      .eq("id", eventId)
      .maybeSingle();

  if (existingError) {
    throw new Error(existingError.message);
  }

  if (!existingEvent) {
    throw new Error(
      "Notification event could not be found"
    );
  }

  return null;
}

export async function processWhatsAppNotification(
  eventId: string
) {
  const supabase = createAdminClient();

  /**
   * IMPORTANT:
   * The notification must first be claimed.
   * If another process already claimed/sent it,
   * this function safely exits.
   */
  const notification = await claimNotification(eventId);

  if (!notification) {
    const { data: existingEvent } = await supabase
      .from("notification_events")
      .select("status")
      .eq("id", eventId)
      .maybeSingle();

    return {
      success: true,
      skipped: true,
      reason:
        existingEvent?.status === "sent"
          ? "Notification already sent"
          : existingEvent?.status === "processing"
            ? "Notification is already being processed"
            : `Notification cannot be processed because status is ${
                existingEvent?.status ?? "unknown"
              }`,
    };
  }

  if (notification.channel !== "whatsapp") {
    await supabase
      .from("notification_events")
      .update({
        status: "skipped",
        last_error: "Unsupported notification channel",
        updated_at: new Date().toISOString(),
      })
      .eq("id", notification.id);

    return {
      success: true,
      skipped: true,
      reason: "Unsupported notification channel",
    };
  }

  try {
    const { data: order, error: orderError } =
      await supabase
        .from("orders")
        .select(
          `
            id,
            order_number,
            customer_name,
            customer_phone,
            customer_whatsapp,
            delivery_address,
            delivery_area,
            subtotal,
            delivery_fee,
            total,
            payment_status,
            order_status,
            paystack_reference
          `
        )
        .eq("id", notification.order_id)
        .single();

    if (orderError || !order) {
      throw new Error(
        orderError?.message ||
          "Order could not be found"
      );
    }

    const { data: items, error: itemsError } =
      await supabase
        .from("order_items")
        .select(
          `
            product_name,
            variant_name,
            quantity,
            unit_price,
            total_price
          `
        )
        .eq("order_id", order.id)
        .order("created_at", {
          ascending: true,
        });

    if (itemsError) {
      throw new Error(itemsError.message);
    }

    const recipient =
      notification.recipient ||
      process.env.PELCY_OWNER_WHATSAPP;

    if (!recipient) {
      throw new Error(
        "PELCY_OWNER_WHATSAPP is not configured"
      );
    }

    const itemLines = (items ?? [])
      .map((item) => {
        const variant = item.variant_name
          ? ` (${item.variant_name})`
          : "";

        return `• ${item.product_name}${variant} × ${
          item.quantity
        } — ${formatMoney(item.total_price)}`;
      })
      .join("\n");

    let messageBody: string;

    if (notification.event_type === "order_created") {
      messageBody = [
        "🛒 NEW PELCY ORDER",
        "",
        `Order: ${order.order_number}`,
        `Customer: ${order.customer_name}`,
        `Phone: ${
          order.customer_whatsapp ||
          order.customer_phone ||
          "Not provided"
        }`,
        "",
        "Items:",
        itemLines || "No items found",
        "",
        `Delivery Area: ${
          order.delivery_area || "Not provided"
        }`,
        `Delivery Address: ${
          order.delivery_address || "Not provided"
        }`,
        `Delivery Fee: ${formatMoney(
          order.delivery_fee
        )}`,
        `Total: ${formatMoney(order.total)}`,
        "",
        `Payment Status: ${readablePaymentStatus(
          order.payment_status
        )}`,
        `Fulfilment Status: ${readableFulfilmentStatus(
          order.order_status
        )}`,
      ].join("\n");
    } else if (
      notification.event_type === "payment_verified"
    ) {
      messageBody = [
        "✅ PELCY PAYMENT VERIFIED",
        "",
        `Order: ${order.order_number}`,
        `Customer: ${order.customer_name}`,
        `Amount Paid: ${formatMoney(order.total)}`,
        `Paystack Reference: ${
          order.paystack_reference ||
          "Not available"
        }`,
        `Fulfilment Status: ${readableFulfilmentStatus(
          order.order_status
        )}`,
        "",
        "Payment has been verified successfully.",
      ].join("\n");
    } else {
      throw new Error(
        `Unsupported notification event: ${notification.event_type}`
      );
    }

    /**
     * Send the actual WhatsApp message.
     */
    const result = await sendWhatsAppText({
      to: recipient,
      body: messageBody,
    });

    const now = new Date().toISOString();

    /**
     * Mark the notification as sent only if this
     * process still owns the processing state.
     */
    const { error: sentError } = await supabase
      .from("notification_events")
      .update({
        status: "sent",
        recipient,
        provider_message_id: result.messageId,
        last_error: null,
        sent_at: now,
        updated_at: now,
      })
      .eq("id", notification.id)
      .eq("status", "processing");

    if (sentError) {
      throw new Error(sentError.message);
    }

    return {
      success: true,
      skipped: false,
      eventId: notification.id,
      eventType: notification.event_type,
      messageId: result.messageId,
    };
  } catch (error) {
    const errorMessage =
      error instanceof Error
        ? error.message
        : "Unknown WhatsApp notification error";

    /**
     * WhatsApp failure must NOT affect the customer's
     * order or payment. Only the notification event
     * itself becomes failed.
     */
    await supabase
      .from("notification_events")
      .update({
        status: "failed",
        last_error: errorMessage,
        updated_at: new Date().toISOString(),
      })
      .eq("id", notification.id)
      .eq("status", "processing");

    throw error;
  }
}

export async function processNextPendingWhatsAppNotification() {
  const supabase = createAdminClient();

  const { data: event, error } = await supabase
    .from("notification_events")
    .select("id")
    .eq("channel", "whatsapp")
    .eq("status", "pending")
    .order("created_at", {
      ascending: true,
    })
    .limit(1)
    .maybeSingle();

  if (error) {
    throw new Error(error.message);
  }

  if (!event) {
    return {
      success: true,
      processed: false,
      message: "No pending WhatsApp notifications",
    };
  }

  const result =
    await processWhatsAppNotification(event.id);

  return {
    success: true,
    processed: !result.skipped,
    result,
  };
}