/**
 * MCP tools for rTrips (travel planning).
 *
 * Tools: rtrips_list_trips, rtrips_get_trip, rtrips_list_itinerary, rtrips_list_expenses
 */

import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import type { SyncServer } from "../local-first/sync-server";
import type { TripDoc } from "../../modules/rtrips/schemas";
import { resolveAccess, accessDeniedResponse } from "./_auth";

const TRIP_PREFIX = ":trips:trips:";

function findTripDocIds(syncServer: SyncServer, space: string): string[] {
	const prefix = `${space}${TRIP_PREFIX}`;
	return syncServer.getDocIds().filter(id => id.startsWith(prefix));
}

export function registerTripsTools(server: McpServer, syncServer: SyncServer) {
	server.tool(
		"rtrips_list_trips",
		"List all trips in a space with budget summaries",
		{
			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 docIds = findTripDocIds(syncServer, space);
			const trips = [];
			for (const docId of docIds) {
				const doc = syncServer.getDoc<TripDoc>(docId);
				if (!doc?.trip) continue;
				const t = doc.trip;
				trips.push({
					id: t.id,
					title: t.title,
					slug: t.slug,
					status: t.status,
					startDate: t.startDate,
					endDate: t.endDate,
					budgetTotal: t.budgetTotal,
					budgetCurrency: t.budgetCurrency,
					destinationCount: Object.keys(doc.destinations || {}).length,
					bookingCount: Object.keys(doc.bookings || {}).length,
					expenseCount: Object.keys(doc.expenses || {}).length,
					createdAt: t.createdAt,
				});
			}
			return { content: [{ type: "text", text: JSON.stringify(trips, null, 2) }] };
		},
	);

	server.tool(
		"rtrips_get_trip",
		"Get full trip details with destinations and bookings",
		{
			space: z.string().describe("Space slug"),
			token: z.string().optional().describe("JWT auth token"),
			trip_id: z.string().describe("Trip ID"),
		},
		async ({ space, token, trip_id }) => {
			const access = await resolveAccess(token, space, false);
			if (!access.allowed) return accessDeniedResponse(access.reason!);

			const docId = `${space}${TRIP_PREFIX}${trip_id}`;
			const doc = syncServer.getDoc<TripDoc>(docId);
			if (!doc?.trip) {
				return { content: [{ type: "text", text: JSON.stringify({ error: "Trip not found" }) }] };
			}

			return {
				content: [{
					type: "text",
					text: JSON.stringify({
						trip: doc.trip,
						destinations: Object.values(doc.destinations || {}),
						bookings: Object.values(doc.bookings || {}),
						packingItemCount: Object.keys(doc.packingItems || {}).length,
						expenseTotal: Object.values(doc.expenses || {}).reduce((sum, e) => sum + (e.amount || 0), 0),
					}, null, 2),
				}],
			};
		},
	);

	server.tool(
		"rtrips_list_itinerary",
		"List itinerary items for a trip, sorted by date",
		{
			space: z.string().describe("Space slug"),
			token: z.string().optional().describe("JWT auth token"),
			trip_id: z.string().describe("Trip ID"),
			date: z.string().optional().describe("Filter by date (YYYY-MM-DD)"),
		},
		async ({ space, token, trip_id, date }) => {
			const access = await resolveAccess(token, space, false);
			if (!access.allowed) return accessDeniedResponse(access.reason!);

			const docId = `${space}${TRIP_PREFIX}${trip_id}`;
			const doc = syncServer.getDoc<TripDoc>(docId);
			if (!doc) {
				return { content: [{ type: "text", text: JSON.stringify({ error: "Trip not found" }) }] };
			}

			let items = Object.values(doc.itinerary || {});
			if (date) items = items.filter(i => i.date === date);
			items.sort((a, b) => (a.date || "").localeCompare(b.date || "") || a.sortOrder - b.sortOrder);

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

	server.tool(
		"rtrips_list_expenses",
		"List trip expenses with totals by category",
		{
			space: z.string().describe("Space slug"),
			token: z.string().optional().describe("JWT auth token"),
			trip_id: z.string().describe("Trip ID"),
		},
		async ({ space, token, trip_id }) => {
			const access = await resolveAccess(token, space, false);
			if (!access.allowed) return accessDeniedResponse(access.reason!);

			const docId = `${space}${TRIP_PREFIX}${trip_id}`;
			const doc = syncServer.getDoc<TripDoc>(docId);
			if (!doc) {
				return { content: [{ type: "text", text: JSON.stringify({ error: "Trip not found" }) }] };
			}

			const expenses = Object.values(doc.expenses || {});
			const total = expenses.reduce((sum, e) => sum + (e.amount || 0), 0);
			const byCategory: Record<string, number> = {};
			for (const e of expenses) {
				const cat = e.category || "uncategorized";
				byCategory[cat] = (byCategory[cat] || 0) + (e.amount || 0);
			}

			return {
				content: [{
					type: "text",
					text: JSON.stringify({
						expenses,
						total,
						currency: doc.trip?.budgetCurrency || null,
						byCategory,
					}, null, 2),
				}],
			};
		},
	);
}
