import { z } from "zod";
import type { db as prodDb } from "../../../db/index.ts";
import {
	bulkUpsertGlobalItems,
	upsertGlobalItem,
} from "../../services/global-item.service.ts";

type Db = typeof prodDb;

interface ToolResult {
	content: Array<{ type: "text"; text: string }>;
}

function textResult(data: unknown): ToolResult {
	return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
}

function errorResult(message: string): ToolResult {
	return {
		content: [{ type: "text", text: JSON.stringify({ error: message }) }],
	};
}

const catalogItemInputSchema = {
	brand: z.string().describe("Brand or manufacturer name"),
	model: z
		.string()
		.describe("Model name — combined with brand forms the unique identifier"),
	category: z
		.string()
		.optional()
		.describe("Category name (e.g., 'Bags', 'Lights')"),
	weightGrams: z.number().optional().describe("Weight in grams"),
	priceCents: z
		.number()
		.optional()
		.describe("MSRP price in cents (e.g., 9999 = $99.99)"),
	imageUrl: z.string().optional().describe("URL to the product image"),
	description: z.string().optional().describe("Product description"),
	sourceUrl: z
		.string()
		.optional()
		.describe("URL to the product page on manufacturer/retailer site"),
	imageCredit: z
		.string()
		.optional()
		.describe("Image credit — photographer or source name"),
	imageSourceUrl: z
		.string()
		.optional()
		.describe("Original URL where the image was sourced from"),
	tags: z
		.array(z.string())
		.optional()
		.describe("Tags for categorization (created automatically if new)"),
};

export const catalogToolDefinitions = [
	{
		name: "upsert_catalog_item",
		description:
			"Add or update a single item in the global catalog. If an item with the same brand and model already exists, it will be updated. Includes attribution fields for image credit and source tracking. Requires authentication.",
		inputSchema: catalogItemInputSchema,
	},
	{
		name: "bulk_upsert_catalog",
		description:
			"Add or update multiple items in the global catalog in a single batch (max 100). All items are processed in one transaction — if any item fails, the entire batch is rolled back. Each item is upserted on (brand, model) uniqueness.",
		inputSchema: {
			items: z
				.array(z.object(catalogItemInputSchema))
				.max(100)
				.describe("Array of catalog items to upsert (max 100 per batch)"),
		},
	},
];

// Catalog tools operate on shared catalog — no userId needed for data scoping
// db is passed for database access
export function registerCatalogTools(db: Db) {
	return {
		upsert_catalog_item: async (args: {
			brand: string;
			model: string;
			category?: string;
			weightGrams?: number;
			priceCents?: number;
			imageUrl?: string;
			description?: string;
			sourceUrl?: string;
			imageCredit?: string;
			imageSourceUrl?: string;
			tags?: string[];
		}): Promise<ToolResult> => {
			try {
				const result = await upsertGlobalItem(db, args);
				return textResult({
					...result.item,
					created: result.created,
				});
			} catch (err) {
				return errorResult((err as Error).message);
			}
		},

		bulk_upsert_catalog: async (args: {
			items: Array<{
				brand: string;
				model: string;
				category?: string;
				weightGrams?: number;
				priceCents?: number;
				imageUrl?: string;
				description?: string;
				sourceUrl?: string;
				imageCredit?: string;
				imageSourceUrl?: string;
				tags?: string[];
			}>;
		}): Promise<ToolResult> => {
			try {
				const result = await bulkUpsertGlobalItems(db, args.items);
				return textResult({
					created: result.created,
					updated: result.updated,
					totalProcessed: result.items.length,
					items: result.items,
				});
			} catch (err) {
				return errorResult((err as Error).message);
			}
		},
	};
}
