import { CORRECT_CITY_SCHEMA, CORRECT_CITY_SYSTEM, buildUserMessage, usageCostUsd } from "./prompt.js";

export const name = "ollama";

// Ollama runs locally → no per-token cost.
export const pricingByModel = {};
const FREE_PRICING = { inputUsdPerM: 0, outputUsdPerM: 0, cacheWriteUsdPerM: 0, cacheReadUsdPerM: 0 };

export const defaultModel = "llama3.2";

export function activeModel() {
  return process.env.OLLAMA_MODEL || defaultModel;
}

export function baseUrl() {
  return (process.env.OLLAMA_BASE_URL || "http://127.0.0.1:11434").replace(/\/$/, "");
}

// "Available" means: the user has explicitly opted into Ollama via env vars.
// We don't probe the Ollama server here — that's done at call time so that
// startup health checks stay synchronous and fast.
export function isAvailable() {
  return (
    String(process.env.AI_PROVIDER || "").toLowerCase() === "ollama" ||
    Boolean(process.env.OLLAMA_MODEL) ||
    Boolean(process.env.OLLAMA_BASE_URL)
  );
}

export async function correctCity({ city, stateCode, candidates }) {
  const model = activeModel();
  const url = `${baseUrl()}/api/chat`;
  const response = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      model,
      messages: [
        { role: "system", content: CORRECT_CITY_SYSTEM },
        { role: "user", content: buildUserMessage({ city, stateCode, candidates }) },
      ],
      // Ollama 0.5+ honors a JSON schema here for structured output.
      format: CORRECT_CITY_SCHEMA,
      stream: false,
      options: { temperature: 0 },
    }),
  });
  if (!response.ok) {
    const text = await response.text().catch(() => "");
    throw new Error(`Ollama ${response.status}: ${text.slice(0, 200)}`);
  }
  const data = await response.json();
  const content = data?.message?.content;
  if (!content) throw new Error("Ollama returned no message content");
  let parsed;
  try { parsed = JSON.parse(content); }
  catch (err) { throw new Error(`Ollama returned invalid JSON: ${content.slice(0, 200)}`); }
  const usage = {
    input_tokens:                Number(data.prompt_eval_count ?? 0),
    output_tokens:               Number(data.eval_count ?? 0),
    cache_creation_input_tokens: 0,
    cache_read_input_tokens:     0,
  };
  return {
    provider: name,
    model,
    correctedCityName: parsed.correctedCityName ?? null,
    confidence: parsed.confidence ?? "low",
    reasoning: parsed.reasoning ?? "",
    usage,
    costUsd: usageCostUsd(usage, FREE_PRICING),
    pricingPerMTok: {
      input: FREE_PRICING.inputUsdPerM,
      output: FREE_PRICING.outputUsdPerM,
      cacheWrite: FREE_PRICING.cacheWriteUsdPerM,
      cacheRead: FREE_PRICING.cacheReadUsdPerM,
    },
  };
}
