'use strict';
//
// Resolve which provider can serve a chat turn that carries attachments,
// given a needed capability set ('vision' for image+pdf, 'audio' for
// audio). When the active provider lacks one or more needed capabilities
// but configured alternatives can carry them, the caller (chat-api.js)
// surfaces a 412 PRECONDITION_FAILED with the alternatives, and the
// frontend prompts the user before switching for the turn.
//
// Phase 3 shipped this at provider-level granularity (Anthropic-yes,
// Ollama-no), good enough for the UX of "Switch to Anthropic for this
// turn?". Phase 4 refines to per-model granularity once we audit each
// provider's listModels() capability tags.

const PROVIDER_CAPABILITY_HINTS = Object.freeze({
  anthropic: { vision: true,  pdf: true,  audio: false, label: 'Anthropic' },
  openai:    { vision: true,  pdf: false, audio: true,  label: 'OpenAI' },
  google:    { vision: true,  pdf: true,  audio: true,  label: 'Google Gemini' },
  gemini:    { vision: true,  pdf: true,  audio: true,  label: 'Google Gemini' },
  moonshot:  { vision: true,  pdf: false, audio: false, label: 'Moonshot / Kimi' },
  ollama:    { vision: false, pdf: false, audio: false, label: 'Ollama (local)' },
  mlx:       { vision: false, pdf: false, audio: false, label: 'MLX (local)' },
});

function providerSupports(providerType, capability) {
  const hint = PROVIDER_CAPABILITY_HINTS[providerType];
  if (!hint) return false;
  return !!hint[capability];
}

/**
 * Inspect the active provider against the capability set. Returns:
 *   {
 *     ok: boolean,                   // true when current provider has all caps
 *     missing: string[],              // capabilities current can't carry
 *     alternatives: [                  // configured providers that CAN carry the
 *       {                               //   missing caps. Empty when none exist.
 *         providerType: 'anthropic',
 *         providerId: 'anthropic-default',
 *         label: 'Anthropic',
 *         capabilities: ['vision'],
 *       }, ...
 *     ],
 *   }
 *
 * @param {Set<string>|string[]} needed - capabilities required by the attachments
 * @param {string} currentProviderType  - active provider type (e.g. 'ollama')
 * @param {Array<{providerType:string, providerId:string}>} configuredProviders
 *        - registered providers (typically `providerAvailability.getConfiguredProviders()`)
 */
function resolveCapability(needed, currentProviderType, configuredProviders = []) {
  const neededSet = new Set(needed);
  if (neededSet.size === 0) {
    return { ok: true, missing: [], alternatives: [] };
  }

  const missing = [];
  for (const cap of neededSet) {
    if (!providerSupports(currentProviderType, cap)) missing.push(cap);
  }
  if (missing.length === 0) {
    return { ok: true, missing: [], alternatives: [] };
  }

  // Find alternatives: any configured provider whose hints cover ALL the
  // missing capabilities. Skip the current one.
  const seen = new Set();
  const alternatives = [];
  for (const p of configuredProviders) {
    if (!p || !p.providerType) continue;
    if (p.providerType === currentProviderType) continue;
    if (seen.has(p.providerType)) continue;
    const hint = PROVIDER_CAPABILITY_HINTS[p.providerType];
    if (!hint) continue;
    const supportsAll = missing.every((c) => !!hint[c]);
    if (!supportsAll) continue;
    seen.add(p.providerType);
    alternatives.push({
      providerType: p.providerType,
      providerId: p.providerId,
      label: hint.label || p.providerType,
      capabilities: missing.filter((c) => hint[c]),
    });
  }

  return { ok: false, missing, alternatives };
}

module.exports = {
  PROVIDER_CAPABILITY_HINTS,
  providerSupports,
  resolveCapability,
};
