/**
 * Order fulfillment service — routes rCart orders to POD providers.
 *
 * Flow:
 * 1. rCart order → paid status
 * 2. This service picks up the order and routes to correct POD provider
 * 3. POD webhooks update tracking → pushed back to rCart order doc
 */

import { PrintfulClient } from "./pod/printful";
import { ProdigiClient } from "./pod/prodigi";
import type { PodOrder, PodRecipient, PodTracking } from "./pod/types";

// ── Types ──

export interface FulfillmentRequest {
	/** rCart order ID */
	orderId: string;
	/** Items to fulfill */
	items: FulfillmentItem[];
	/** Shipping address */
	recipient: PodRecipient;
	/** Optional metadata */
	metadata?: Record<string, string>;
}

export interface FulfillmentItem {
	/** Design image public URL */
	imageUrl: string;
	/** POD provider to use */
	provider: "printful" | "prodigi";
	/** Provider-specific SKU */
	sku: string;
	/** Quantity */
	quantity: number;
	/** Size variant (for apparel) */
	size?: string;
	/** Color variant (for apparel) */
	color?: string;
	/** Placement on product */
	placement?: string;
}

export interface FulfillmentResult {
	orderId: string;
	provider: "printful" | "prodigi";
	providerOrderId: string;
	status: string;
	items: FulfillmentItem[];
	submittedAt: string;
}

// ── In-memory fulfillment tracking ──
// Maps rCart orderId → fulfillment results
const fulfillmentLog = new Map<string, FulfillmentResult[]>();

// ── Service ──

const printful = new PrintfulClient();
const prodigi = new ProdigiClient();

/**
 * Submit an order to the appropriate POD provider(s).
 *
 * If items span multiple providers, creates separate orders per provider.
 */
export async function submitFulfillment(
	request: FulfillmentRequest,
): Promise<FulfillmentResult[]> {
	const results: FulfillmentResult[] = [];

	// Group items by provider
	const printfulItems = request.items.filter((i) => i.provider === "printful");
	const prodigiItems = request.items.filter((i) => i.provider === "prodigi");

	// Submit Printful items
	if (printfulItems.length > 0) {
		const result = await submitToPrintful(
			request.orderId,
			printfulItems,
			request.recipient,
		);
		results.push(result);
	}

	// Submit Prodigi items
	if (prodigiItems.length > 0) {
		const result = await submitToProdigi(
			request.orderId,
			prodigiItems,
			request.recipient,
			request.metadata,
		);
		results.push(result);
	}

	// Store in tracking log
	fulfillmentLog.set(request.orderId, results);

	return results;
}

async function submitToPrintful(
	orderId: string,
	items: FulfillmentItem[],
	recipient: PodRecipient,
): Promise<FulfillmentResult> {
	if (!printful.enabled) {
		throw new Error("Printful API not configured");
	}

	// Resolve catalog variant IDs for each item
	const orderItems = await Promise.all(
		items.map(async (item) => {
			const productId = parseInt(item.sku, 10);
			let catalogVariantId: number | null = null;

			if (item.size) {
				catalogVariantId = await printful.resolveVariantId(
					productId,
					item.size,
					item.color || "Black",
				);
			}

			if (!catalogVariantId) {
				// Fallback: get first available variant
				const variants = await printful.getCatalogVariants(productId);
				catalogVariantId = variants[0]?.id || 0;
			}

			return {
				catalogVariantId,
				quantity: item.quantity,
				imageUrl: item.imageUrl,
				placement: item.placement || "front",
			};
		}),
	);

	const order = await printful.createOrder(orderItems, recipient);

	return {
		orderId,
		provider: "printful",
		providerOrderId: order.id,
		status: order.status,
		items,
		submittedAt: new Date().toISOString(),
	};
}

async function submitToProdigi(
	orderId: string,
	items: FulfillmentItem[],
	recipient: PodRecipient,
	metadata?: Record<string, string>,
): Promise<FulfillmentResult> {
	if (!prodigi.enabled) {
		throw new Error("Prodigi API not configured");
	}

	const prodigiItems = items.map((item) => ({
		sku: item.sku,
		copies: item.quantity,
		sizing: "fillPrintArea" as const,
		assets: [{ printArea: "default", url: item.imageUrl }],
	}));

	const order = await prodigi.createOrder(
		prodigiItems,
		recipient,
		"Budget",
		metadata ? { ...metadata, rCartOrderId: orderId } : { rCartOrderId: orderId },
	);

	return {
		orderId,
		provider: "prodigi",
		providerOrderId: order.id,
		status: order.status,
		items,
		submittedAt: new Date().toISOString(),
	};
}

// ── Webhook handlers ──

export interface WebhookEvent {
	provider: "printful" | "prodigi";
	type: string;
	orderId: string;
	tracking?: PodTracking;
	status?: string;
	raw: unknown;
}

/**
 * Process a Printful webhook event.
 * Returns parsed event data for the caller to update rCart.
 */
export function parsePrintfulWebhook(body: any): WebhookEvent | null {
	if (!body?.type || !body?.data) return null;

	const event: WebhookEvent = {
		provider: "printful",
		type: body.type,
		orderId: String(body.data?.order?.id || body.data?.id || ""),
		raw: body,
	};

	// Extract tracking info from shipment events
	if (body.type === "package_shipped" || body.type === "order_updated") {
		const shipment = body.data?.shipment || body.data;
		if (shipment?.tracking_number) {
			event.tracking = {
				carrier: shipment.carrier || "",
				trackingNumber: shipment.tracking_number,
				trackingUrl: shipment.tracking_url || "",
			};
		}
		event.status = body.data?.order?.status || body.data?.status;
	}

	return event;
}

/**
 * Process a Prodigi webhook event.
 */
export function parseProdigiWebhook(body: any): WebhookEvent | null {
	if (!body?.topic) return null;

	const order = body.order || body;

	const event: WebhookEvent = {
		provider: "prodigi",
		type: body.topic,
		orderId: String(order?.id || ""),
		raw: body,
	};

	// Extract tracking from shipment events
	if (body.topic === "order.shipped") {
		const shipment = order?.shipments?.[0];
		if (shipment) {
			event.tracking = {
				carrier: shipment.carrier || "",
				trackingNumber: shipment.trackingNumber || "",
				trackingUrl: shipment.trackingUrl || "",
			};
		}
	}

	event.status = order?.status?.stage;

	return event;
}

// ── Tracking lookup ──

/**
 * Get fulfillment status for an rCart order.
 */
export function getFulfillmentStatus(orderId: string): FulfillmentResult[] | null {
	return fulfillmentLog.get(orderId) || null;
}

/**
 * Get tracking info from the POD provider.
 */
export async function getTrackingInfo(
	provider: "printful" | "prodigi",
	providerOrderId: string,
): Promise<PodTracking | null> {
	try {
		if (provider === "printful") {
			const order = await printful.getOrder(providerOrderId);
			const raw = order.raw as any;
			const shipment = raw?.shipments?.[0];
			if (shipment?.tracking_number) {
				return {
					carrier: shipment.carrier || "",
					trackingNumber: shipment.tracking_number,
					trackingUrl: shipment.tracking_url || "",
				};
			}
		} else {
			const order = await prodigi.getOrder(providerOrderId);
			const raw = order.raw as any;
			const shipment = raw?.order?.shipments?.[0];
			if (shipment?.trackingNumber) {
				return {
					carrier: shipment.carrier || "",
					trackingNumber: shipment.trackingNumber,
					trackingUrl: shipment.trackingUrl || "",
				};
			}
		}
	} catch (err) {
		console.warn(`[rSwag] Failed to get tracking for ${provider} order ${providerOrderId}:`, err);
	}

	return null;
}
