/**
 * MCP tool exposing administrative units that cover a given point.
 */

import BaseTool from "./BaseTool.js";
import { z } from "zod";

import { getAdminUnits, ADMINEXPRESS_TYPES, ADMINEXPRESS_SOURCE } from "../gpf/adminexpress.js";
import { READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONS } from "../helpers/toolAnnotations.js";
import { featureRefSchema, lonSchema, latSchema } from "../helpers/schemas.js";
import logger from "../logger.js";

// --- Schema ---

const adminexpressInputSchema = z.object({
  lon: lonSchema,
  lat: latSchema,
}).strict();

// --- Types ---

type AdminexpressInput = z.infer<typeof adminexpressInputSchema>;

const adminexpressResultSchema = z
  .object({
    type: z.string().describe(`Le type d'unité administrative (${ADMINEXPRESS_TYPES.join(", ")}).`),
    id: z.string().describe("L'identifiant de l'unité administrative."),
    bbox: z.array(z.number()).describe("La boîte englobante de l'unité administrative.").optional(),
    feature_ref: featureRefSchema.describe("Référence WFS réutilisable, notamment avec `gpf_wfs_get_features` et `intersects_feature_filter`."),
  })
  .catchall(z.unknown());

const adminexpressOutputSchema = z.object({
  results: z.array(adminexpressResultSchema).describe("La liste des unités administratives couvrant le point demandé."),
});

// --- Tool ---

class AdminexpressTool extends BaseTool<AdminexpressInput> {
  name = "adminexpress";
  title = "Unités administratives";
  annotations = READ_ONLY_OPEN_WORLD_TOOL_ANNOTATIONS;
  description = [
    `Renvoie, pour un point donné par sa \`longitude\` et sa \`latitude\`, la liste des unités administratives (${ADMINEXPRESS_TYPES.join(", ")}) qui le couvrent, sous forme d'objets typés contenant leurs propriétés administratives.`,
    "Les résultats incluent un `feature_ref` WFS réutilisable. Les propriétés incluent notamment le code INSEE.",
    "Le `feature_ref` de chaque unité administrative est directement réutilisable dans `gpf_wfs_get_features` avec `intersects_feature_filter` pour interroger d'autres données sur cette emprise.",
    "Pour récupérer exactement l'objet correspondant au `feature_ref`, utiliser `gpf_wfs_get_feature_by_id`.",
    `(source : ${ADMINEXPRESS_SOURCE}).`
  ].join("\n");
  protected outputSchemaShape = adminexpressOutputSchema;

  schema = adminexpressInputSchema;

  /**
   * Looks up the administrative units covering the requested point.
   *
   * @param input Normalized tool input.
   * @returns The matching administrative units enriched with reusable `feature_ref` metadata.
   */
  async execute(input: AdminexpressInput) {
    logger.info(`[tool] execute ${this.name} ...`, {
      input: input
    });

    return {
      results: await getAdminUnits(input.lon, input.lat),
    };
  }
}

export default AdminexpressTool;
