/**
 * MCP tools for rCart (catalog, shopping carts, group buys, payments).
 *
 * Tools: rcart_list_catalog, rcart_list_carts, rcart_get_cart, rcart_list_group_buys
 */

import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import type { SyncServer } from "../local-first/sync-server";
import { catalogDocId, shoppingCartIndexDocId } from "../../modules/rcart/schemas";
import type { CatalogDoc, ShoppingCartIndexDoc, ShoppingCartDoc, GroupBuyDoc } from "../../modules/rcart/schemas";
import { resolveAccess, accessDeniedResponse } from "./_auth";

const CART_PREFIX = ":cart:shopping:";
const GROUP_BUY_PREFIX = ":cart:group-buys:";

export function registerCartTools(server: McpServer, syncServer: SyncServer) {
	server.tool(
		"rcart_list_catalog",
		"List product catalog entries in a space",
		{
			space: z.string().describe("Space slug"),
			token: z.string().optional().describe("JWT auth token"),
			search: z.string().optional().describe("Search in title/tags"),
			limit: z.number().optional().describe("Max results (default 50)"),
		},
		async ({ space, token, search, limit }) => {
			const access = await resolveAccess(token, space, false);
			if (!access.allowed) return accessDeniedResponse(access.reason!);

			const doc = syncServer.getDoc<CatalogDoc>(catalogDocId(space));
			if (!doc) {
				return { content: [{ type: "text", text: JSON.stringify({ error: "No catalog found" }) }] };
			}

			let items = Object.values(doc.items || {});
			if (search) {
				const q = search.toLowerCase();
				items = items.filter(i =>
					i.title.toLowerCase().includes(q) ||
					i.tags.some(t => t.toLowerCase().includes(q)),
				);
			}
			items = items.slice(0, limit || 50);

			const summary = items.map(i => ({
				id: i.id,
				title: i.title,
				productType: i.productType,
				substrates: i.substrates,
				tags: i.tags,
				status: i.status,
				createdAt: i.createdAt,
			}));

			return { content: [{ type: "text", text: JSON.stringify(summary, null, 2) }] };
		},
	);

	server.tool(
		"rcart_list_carts",
		"List shopping carts in a space with status and funding",
		{
			space: z.string().describe("Space slug"),
			token: z.string().optional().describe("JWT auth token"),
			status: z.string().optional().describe("Filter by status (OPEN, FUNDING, FUNDED, ORDERED, CLOSED)"),
		},
		async ({ space, token, status }) => {
			const access = await resolveAccess(token, space, false);
			if (!access.allowed) return accessDeniedResponse(access.reason!);

			const indexDoc = syncServer.getDoc<ShoppingCartIndexDoc>(shoppingCartIndexDocId(space));
			if (!indexDoc) {
				return { content: [{ type: "text", text: JSON.stringify({ error: "No carts found" }) }] };
			}

			let carts = Object.entries(indexDoc.carts || {}).map(([id, c]) => ({ id, ...c }));
			if (status) carts = carts.filter(c => c.status === status);

			return { content: [{ type: "text", text: JSON.stringify(carts, null, 2) }] };
		},
	);

	server.tool(
		"rcart_get_cart",
		"Get full shopping cart with items and contributions",
		{
			space: z.string().describe("Space slug"),
			token: z.string().optional().describe("JWT auth token"),
			cart_id: z.string().describe("Cart ID"),
		},
		async ({ space, token, cart_id }) => {
			const access = await resolveAccess(token, space, false);
			if (!access.allowed) return accessDeniedResponse(access.reason!);

			const docId = `${space}${CART_PREFIX}${cart_id}`;
			const doc = syncServer.getDoc<ShoppingCartDoc>(docId);
			if (!doc?.cart) {
				return { content: [{ type: "text", text: JSON.stringify({ error: "Cart not found" }) }] };
			}

			return {
				content: [{
					type: "text",
					text: JSON.stringify({
						cart: doc.cart,
						items: Object.values(doc.items || {}),
						contributions: Object.values(doc.contributions || {}),
						eventCount: doc.events?.length ?? 0,
					}, null, 2),
				}],
			};
		},
	);

	server.tool(
		"rcart_list_group_buys",
		"List group buys with pledge tallies",
		{
			space: z.string().describe("Space slug"),
			token: z.string().optional().describe("JWT auth token"),
			status: z.string().optional().describe("Filter by status (OPEN, LOCKED, ORDERED, CANCELLED)"),
		},
		async ({ space, token, status }) => {
			const access = await resolveAccess(token, space, false);
			if (!access.allowed) return accessDeniedResponse(access.reason!);

			const prefix = `${space}${GROUP_BUY_PREFIX}`;
			const docIds = syncServer.getDocIds().filter(id => id.startsWith(prefix));
			let buys: any[] = [];

			for (const docId of docIds) {
				const doc = syncServer.getDoc<GroupBuyDoc>(docId);
				if (!doc?.buy) continue;
				buys.push({
					id: doc.buy.id,
					title: doc.buy.title,
					status: doc.buy.status,
					totalPledged: doc.buy.totalPledged,
					pledgeCount: Object.keys(doc.pledges || {}).length,
					tiers: doc.buy.tiers,
					closesAt: doc.buy.closesAt,
					createdAt: doc.buy.createdAt,
				});
			}

			if (status) buys = buys.filter(b => b.status === status);
			return { content: [{ type: "text", text: JSON.stringify(buys, null, 2) }] };
		},
	);
}
