import { action } from "./_generated/server";
import { internal } from "./_generated/api";
import { v } from "convex/values";
import { getShipmentRateObjectId } from "./model/shippo";

const SHIPPO_TRANSACTIONS_URL = "https://api.goshippo.com/transactions/";

type LabelResult =
  | { success: true; trackingNumber: string; trackingUrl: string }
  | { success: false; code: string; message: string };

export const createShippingLabel = action({
  args: { orderId: v.id("orders") },
  handler: async (ctx, { orderId }): Promise<LabelResult> => {
    // 1. Auth — must be admin
    const userId = await ctx.runQuery(internal.checkout.getCurrentUserId);
    const user = await ctx.runQuery(internal.users.getById, { userId });
    if (user.role !== "admin" && user.role !== "super_admin") {
      throw new Error("Unauthorized: admin access required");
    }

    // 2. Load order
    const order = await ctx.runQuery(internal.orders.getOrderForRefund, {
      id: orderId,
    });
    if (!order) throw new Error("Order not found");

    // 3. Validate — only confirmed orders without an existing label
    if (order.status !== "confirmed") {
      return {
        success: false,
        code: "INVALID_STATUS",
        message: "Only confirmed orders can receive a shipping label.",
      };
    }
    if (order.trackingNumber) {
      return {
        success: false,
        code: "DUPLICATE_LABEL",
        message: "A shipping label already exists for this order.",
      };
    }
    if (!order.shippoShipmentId) {
      return {
        success: false,
        code: "NO_SHIPMENT",
        message: "Order has no Shippo shipment ID.",
      };
    }

    // 4. Resolve rate object ID from the stored shipment
    let rateObjectId: string;
    try {
      rateObjectId = await getShipmentRateObjectId(
        order.shippoShipmentId,
        order.shippingServiceCode,
        order.carrier,
      );
    } catch (err) {
      const message =
        err instanceof Error ? err.message : "Failed to resolve shipping rate.";
      return { success: false, code: "RATE_ERROR", message };
    }

    // 5. Purchase label via Shippo POST /transactions (synchronous)
    const apiKey = process.env.SHIPPO_API_KEY;
    if (!apiKey) {
      return {
        success: false,
        code: "CONFIG_ERROR",
        message: "Shippo API key not configured.",
      };
    }

    let txResponse: Response;
    try {
      txResponse = await fetch(SHIPPO_TRANSACTIONS_URL, {
        method: "POST",
        headers: {
          Authorization: `ShippoToken ${apiKey}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ rate: rateObjectId, async: false }),
      });
    } catch {
      return {
        success: false,
        code: "SHIPPO_UNREACHABLE",
        message: "Could not reach Shippo to create the label.",
      };
    }

    if (!txResponse.ok) {
      let detail = "";
      try {
        detail = JSON.stringify(await txResponse.json());
      } catch {}
      console.error(
        "Shippo /transactions/ error:",
        txResponse.status,
        detail,
      );
      return {
        success: false,
        code: "SHIPPO_ERROR",
        message: `Shippo returned status ${txResponse.status}.`,
      };
    }

    let tx: {
      object_id: string;
      status: string;
      tracking_number?: string;
      tracking_url_provider?: string;
      label_url?: string;
      eta?: string;
      messages?: Array<{ source: string; text: string; code: string }>;
    };
    try {
      tx = await txResponse.json();
    } catch {
      return {
        success: false,
        code: "PARSE_ERROR",
        message: "Shippo response could not be parsed.",
      };
    }

    if (tx.status !== "SUCCESS") {
      const errMsg =
        tx.messages?.map((m) => m.text).join("; ") ?? "Unknown Shippo error";
      console.error("Shippo transaction failed:", tx.status, errMsg);
      const isExpired = tx.messages?.some(
        (m) =>
          m.code === "carrier_account_invalid_credentials" ||
          m.text.toLowerCase().includes("expired"),
      );
      return {
        success: false,
        code: isExpired ? "RATE_EXPIRED" : "SHIPPO_ERROR",
        message: isExpired
          ? "The shipping rate has expired. Please try again."
          : errMsg,
      };
    }

    if (!tx.tracking_number) {
      return {
        success: false,
        code: "NO_TRACKING",
        message: "Shippo returned success but no tracking number.",
      };
    }

    // 6. Persist label data and update order status
    const etaMs =
      tx.eta && !isNaN(new Date(tx.eta).getTime())
        ? new Date(tx.eta).getTime()
        : undefined;

    await ctx.runMutation(internal.orders.applyLabel, {
      orderId,
      adminUserId: userId,
      trackingNumber: tx.tracking_number,
      trackingUrl: tx.tracking_url_provider ?? "",
      labelUrl: tx.label_url,
      estimatedDelivery: etaMs,
    });

    return {
      success: true,
      trackingNumber: tx.tracking_number,
      trackingUrl: tx.tracking_url_provider ?? "",
    };
  },
});
