import { z } from "zod";
import type { db as prodDb } from "../../../db/index.ts";
import {
	createSetup,
	getAllSetups,
	getSetupWithItems,
	syncSetupItems,
	updateSetup,
} from "../../services/setup.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 }) }],
	};
}

export const setupToolDefinitions = [
	{
		name: "list_setups",
		description:
			"List all gear setups with item counts and weight/cost totals.",
		inputSchema: {},
	},
	{
		name: "get_setup",
		description: "Get a setup with all its items and details.",
		inputSchema: {
			id: z.number().describe("Setup ID"),
		},
	},
	{
		name: "create_setup",
		description: "Create a new gear setup (e.g. 'Bikepacking weekend').",
		inputSchema: {
			name: z.string().describe("Setup name"),
		},
	},
	{
		name: "update_setup",
		description:
			"Update a setup's name and/or replace its item list. Pass itemIds to set exactly which items belong to this setup.",
		inputSchema: {
			id: z.number().describe("Setup ID"),
			name: z.string().optional().describe("New setup name"),
			itemIds: z
				.array(z.number())
				.optional()
				.describe("Array of item IDs to include in the setup"),
		},
	},
];

export function registerSetupTools(db: Db, userId: number) {
	return {
		list_setups: async (): Promise<ToolResult> => {
			try {
				const setupList = await getAllSetups(db, userId);
				return textResult(setupList);
			} catch (err) {
				return errorResult((err as Error).message);
			}
		},

		get_setup: async (args: { id: number }): Promise<ToolResult> => {
			try {
				const setup = await getSetupWithItems(db, userId, args.id);
				if (!setup) return errorResult(`Setup ${args.id} not found`);
				return textResult(setup);
			} catch (err) {
				return errorResult((err as Error).message);
			}
		},

		create_setup: async (args: { name: string }): Promise<ToolResult> => {
			try {
				const setup = await createSetup(db, userId, args);
				return textResult(setup);
			} catch (err) {
				return errorResult((err as Error).message);
			}
		},

		update_setup: async (args: {
			id: number;
			name?: string;
			itemIds?: number[];
		}): Promise<ToolResult> => {
			try {
				let setup = null;
				if (args.name) {
					setup = await updateSetup(db, userId, args.id, { name: args.name });
					if (!setup) return errorResult(`Setup ${args.id} not found`);
				}
				if (args.itemIds) {
					await syncSetupItems(db, userId, args.id, args.itemIds);
				}
				// Return updated setup with items
				const result = await getSetupWithItems(db, userId, args.id);
				if (!result) return errorResult(`Setup ${args.id} not found`);
				return textResult(result);
			} catch (err) {
				return errorResult((err as Error).message);
			}
		},
	};
}
