/**
 * Prodigi v4 API client.
 *
 * Handles order submission, product specs, and quotes.
 * Sandbox: https://api.sandbox.prodigi.com/v4.0/
 * Production: https://api.prodigi.com/v4.0/
 */

import type { PodOrder, PodRecipient, PodQuote } from "./types";

const SANDBOX_URL = "https://api.sandbox.prodigi.com/v4.0";
const PRODUCTION_URL = "https://api.prodigi.com/v4.0";

export class ProdigiClient {
	private apiKey: string;
	private baseUrl: string;
	readonly enabled: boolean;

	constructor() {
		this.apiKey = process.env.PRODIGI_API_KEY || "";
		const sandbox = process.env.POD_SANDBOX_MODE !== "false";
		this.baseUrl = sandbox ? SANDBOX_URL : PRODUCTION_URL;
		this.enabled = !!this.apiKey;
	}

	private get headers(): Record<string, string> {
		return {
			"X-API-Key": this.apiKey,
			"Content-Type": "application/json",
		};
	}

	/**
	 * Create a Prodigi print order.
	 *
	 * Items should include: sku, copies, sizing, assets.
	 * Recipient uses Prodigi address format.
	 */
	async createOrder(
		items: {
			sku: string;
			copies: number;
			sizing?: "fillPrintArea" | "fitPrintArea" | "stretchToPrintArea";
			assets: { printArea: string; url: string }[];
		}[],
		recipient: PodRecipient,
		shippingMethod: "Budget" | "Standard" | "Express" = "Budget",
		metadata?: Record<string, string>,
	): Promise<PodOrder> {
		if (!this.enabled) throw new Error("Prodigi API key not configured");

		const payload: any = {
			shippingMethod,
			recipient: {
				name: recipient.name,
				...(recipient.email ? { email: recipient.email } : {}),
				address: {
					line1: recipient.address1,
					...(recipient.address2 ? { line2: recipient.address2 } : {}),
					townOrCity: recipient.city,
					...(recipient.stateCode ? { stateOrCounty: recipient.stateCode } : {}),
					postalOrZipCode: recipient.zip,
					countryCode: recipient.countryCode,
				},
			},
			items: items.map((item) => ({
				sku: item.sku,
				copies: item.copies,
				sizing: item.sizing || "fillPrintArea",
				assets: item.assets,
			})),
		};

		if (metadata) payload.metadata = metadata;

		const resp = await fetch(`${this.baseUrl}/Orders`, {
			method: "POST",
			headers: this.headers,
			body: JSON.stringify(payload),
		});
		if (!resp.ok) {
			const text = await resp.text();
			throw new Error(`Prodigi order error ${resp.status}: ${text.slice(0, 500)}`);
		}

		const result = await resp.json();

		return {
			id: String(result.id || result.order?.id || ""),
			provider: "prodigi",
			status: result.status?.stage || "InProgress",
			items: items.map((i) => ({
				sku: i.sku,
				quantity: i.copies,
				imageUrl: i.assets[0]?.url || "",
			})),
			recipient,
			createdAt: new Date().toISOString(),
			raw: result,
		};
	}

	async getOrder(orderId: string): Promise<PodOrder> {
		const resp = await fetch(`${this.baseUrl}/Orders/${orderId}`, {
			headers: this.headers,
		});
		if (!resp.ok) throw new Error(`Prodigi get order error: ${resp.status}`);

		const result = await resp.json();
		const order = result.order || result;

		return {
			id: String(order.id || orderId),
			provider: "prodigi",
			status: order.status?.stage || "unknown",
			items: [],
			recipient: { name: "", address1: "", city: "", countryCode: "", zip: "" },
			createdAt: order.created || new Date().toISOString(),
			raw: result,
		};
	}

	async getProduct(sku: string): Promise<any> {
		const resp = await fetch(`${this.baseUrl}/products/${sku}`, {
			headers: this.headers,
		});
		if (!resp.ok) throw new Error(`Prodigi product error: ${resp.status}`);
		return resp.json();
	}

	async getQuote(
		items: { sku: string; copies: number }[],
		shippingMethod: "Budget" | "Standard" | "Express" = "Budget",
		destinationCountry = "US",
	): Promise<PodQuote> {
		const payload = {
			shippingMethod,
			destinationCountryCode: destinationCountry,
			items: items.map((i) => ({ sku: i.sku, copies: i.copies })),
		};

		const resp = await fetch(`${this.baseUrl}/quotes`, {
			method: "POST",
			headers: this.headers,
			body: JSON.stringify(payload),
		});
		if (!resp.ok) throw new Error(`Prodigi quote error: ${resp.status}`);

		const result = await resp.json();
		const quotes = result.quotes || [result];
		const q = quotes[0] || {};

		return {
			items: (q.items || []).map((i: any) => ({
				sku: i.sku,
				unitCost: parseFloat(i.unitCost?.amount || "0"),
				quantity: i.copies || 1,
			})),
			shippingCost: parseFloat(q.shipmentSummary?.items?.[0]?.cost?.amount || "0"),
			totalCost: parseFloat(q.totalCost?.amount || "0"),
			currency: q.totalCost?.currency || "USD",
		};
	}
}
