import { config } from '../config.js';
import { placeOntology, placeOntologyTags } from '../ontology/place-ontology.js';

type OpenRouterResponse = {
  choices?: Array<{
    finish_reason?: string;
    message?: {
      content?: string;
    };
  }>;
};

export type PlaceIntent = {
  tags: string[];
  summary: string;
};

export async function classifyPlaceIntent(input: {
  transcript: string;
}): Promise<PlaceIntent> {
  if (!config.openRouterApiKey) {
    throw new Error('OPENROUTER_API_KEY is required for voice place filters.');
  }

  const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
    method: 'POST',
    headers: {
      authorization: `Bearer ${config.openRouterApiKey}`,
      'content-type': 'application/json',
      'http-referer': config.webAppUrl,
      'x-title': 'MapFlow',
    },
    body: JSON.stringify({
      model: config.openRouterModel,
      provider: { require_parameters: true },
      temperature: 0.1,
      max_tokens: 900,
      response_format: {
        type: 'json_schema',
        json_schema: {
          name: 'place_voice_filter',
          strict: true,
          schema: {
            type: 'object',
            additionalProperties: false,
            required: ['tags', 'summary'],
            properties: {
              tags: {
                type: 'array',
                maxItems: 8,
                items: { type: 'string', enum: placeOntologyTags },
              },
              summary: { type: 'string' },
            },
          },
        },
      },
      messages: [
        {
          role: 'system',
          content:
            'You convert a user voice request for a place into MapFlow ontology tags. Return one JSON object. Use only allowed tags. Do not recommend places.',
        },
        {
          role: 'user',
          content: JSON.stringify({
            task:
              'Select tags explicitly implied by the request. If the request is vague, return an empty tags array.',
            ontology: placeOntology,
            transcript: input.transcript,
          }),
        },
      ],
    }),
  });

  if (!response.ok) {
    const errorBody = await response.text();
    throw new Error(
      `OpenRouter voice filter failed with ${response.status}: ${errorBody.slice(0, 500)}`,
    );
  }

  const payload = (await response.json()) as OpenRouterResponse;
  const choice = payload.choices?.[0];
  const content = choice?.message?.content?.trim();
  if (!content) {
    throw new Error(
      `OpenRouter returned an empty voice filter for ${config.openRouterModel}; finish_reason=${choice?.finish_reason ?? 'missing'}.`,
    );
  }

  const intent = JSON.parse(content) as PlaceIntent;
  assertValidPlaceIntent(intent);
  return intent;
}

function assertValidPlaceIntent(intent: PlaceIntent) {
  if (!Array.isArray(intent.tags)) {
    throw new Error('OpenRouter voice filter tags must be an array.');
  }
  for (const tag of intent.tags) {
    if (!placeOntologyTags.includes(tag)) {
      throw new Error(`OpenRouter voice filter returned unsupported tag: ${tag}.`);
    }
  }
  if (typeof intent.summary !== 'string') {
    throw new Error('OpenRouter voice filter summary must be a string.');
  }
}
