/**
 * MCP tools for rExchange (P2P trading).
 *
 * Tools: rexchange_list_intents, rexchange_list_trades,
 *        rexchange_list_pools, rexchange_get_reputation
 */

import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import type { SyncServer } from "../local-first/sync-server";
import {
	exchangeIntentsDocId, exchangeTradesDocId,
	exchangePoolsDocId, exchangeReputationDocId,
} from "../../modules/rexchange/schemas";
import type {
	ExchangeIntentsDoc, ExchangeTradesDoc,
	ExchangePoolsDoc, ExchangeReputationDoc,
} from "../../modules/rexchange/schemas";
import { resolveAccess, accessDeniedResponse } from "./_auth";

export function registerExchangeTools(server: McpServer, syncServer: SyncServer) {
	server.tool(
		"rexchange_list_intents",
		"List P2P trading intents (buy/sell offers)",
		{
			space: z.string().describe("Space slug"),
			token: z.string().optional().describe("JWT auth token"),
			side: z.string().optional().describe("Filter by side (buy or sell)"),
			status: z.string().optional().describe("Filter by status (active, matched, completed, cancelled, expired)"),
			limit: z.number().optional().describe("Max results (default 50)"),
		},
		async ({ space, token, side, status, limit }) => {
			const access = await resolveAccess(token, space, false);
			if (!access.allowed) return accessDeniedResponse(access.reason!);

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

			let intents = Object.values(doc.intents || {});
			if (side) intents = intents.filter(i => i.side === side);
			if (status) intents = intents.filter(i => i.status === status);
			intents.sort((a, b) => b.createdAt - a.createdAt);
			intents = intents.slice(0, limit || 50);

			const summary = intents.map(i => ({
				id: i.id, creatorName: i.creatorName, side: i.side,
				tokenId: i.tokenId, fiatCurrency: i.fiatCurrency,
				tokenAmountMin: i.tokenAmountMin, tokenAmountMax: i.tokenAmountMax,
				rateType: i.rateType, rateFixed: i.rateFixed,
				paymentMethods: i.paymentMethods, status: i.status,
				isStandingOrder: i.isStandingOrder, createdAt: i.createdAt,
			}));

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

	server.tool(
		"rexchange_list_trades",
		"List P2P trades with status and amounts",
		{
			space: z.string().describe("Space slug"),
			token: z.string().optional().describe("JWT auth token"),
			status: z.string().optional().describe("Filter by trade status"),
			limit: z.number().optional().describe("Max results (default 20)"),
		},
		async ({ space, token, status, limit }) => {
			const access = await resolveAccess(token, space, false);
			if (!access.allowed) return accessDeniedResponse(access.reason!);

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

			let trades = Object.values(doc.trades || {});
			if (status) trades = trades.filter(t => t.status === status);
			trades.sort((a, b) => b.createdAt - a.createdAt);
			trades = trades.slice(0, limit || 20);

			const summary = trades.map(t => ({
				id: t.id, buyerName: t.buyerName, sellerName: t.sellerName,
				tokenId: t.tokenId, tokenAmount: t.tokenAmount,
				fiatCurrency: t.fiatCurrency, fiatAmount: t.fiatAmount,
				agreedRate: t.agreedRate, paymentMethod: t.paymentMethod,
				status: t.status, chatMessageCount: t.chatMessages?.length ?? 0,
				createdAt: t.createdAt, completedAt: t.completedAt,
			}));

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

	server.tool(
		"rexchange_list_pools",
		"List liquidity pool positions",
		{
			space: z.string().describe("Space slug"),
			token: z.string().optional().describe("JWT auth token"),
		},
		async ({ space, token }) => {
			const access = await resolveAccess(token, space, false);
			if (!access.allowed) return accessDeniedResponse(access.reason!);

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

			const positions = Object.values(doc.positions || {}).map(p => ({
				id: p.id, creatorName: p.creatorName,
				tokenId: p.tokenId, fiatCurrency: p.fiatCurrency,
				tokenRemaining: p.tokenRemaining, fiatRemaining: p.fiatRemaining,
				spreadBps: p.spreadBps, feesEarnedToken: p.feesEarnedToken,
				feesEarnedFiat: p.feesEarnedFiat, tradesMatched: p.tradesMatched,
				status: p.status,
			}));

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

	server.tool(
		"rexchange_get_reputation",
		"Get trader reputation scores",
		{
			space: z.string().describe("Space slug"),
			token: z.string().optional().describe("JWT auth token"),
			did: z.string().optional().describe("Filter by specific DID"),
		},
		async ({ space, token, did }) => {
			const access = await resolveAccess(token, space, false);
			if (!access.allowed) return accessDeniedResponse(access.reason!);

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

			let records = Object.values(doc.records || {});
			if (did) records = records.filter(r => r.did === did);
			records.sort((a, b) => b.score - a.score);

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