/**
 * CapabilityMatrixRegistry - Provider capability matrix lookup
 *
 * Implements DD §12.2.
 * Holds ProviderCapabilityMatrix rows with nested supports/conversion/quality/cost tiers.
 *
 * @module packages/llm/src/CapabilityMatrix
 */

export interface SupportsMap {
  text_input: boolean
  text_output: boolean
  streaming: boolean
  tool_use: boolean
  parallel_tool_use: boolean
  structured_output: boolean
  json_mode: boolean
  thinking: boolean
  prompt_cache: boolean
  system_prompt: boolean
  image_input: boolean
  image_output: boolean
  audio_input: boolean
  audio_output: boolean
  file_input: boolean
  computer_use: boolean
  long_context: boolean
}

export interface ConversionMap {
  from_anthropic_canonical?: boolean
  tool_schema?: 'native' | 'emulated' | 'none'
  image_input?: 'base64' | 'url' | 'none'
  thinking?: 'native' | 'emulated' | 'none'
  cache_control?: 'anthropic' | 'openai' | 'none'
}

export interface ProviderCapability {
  provider: string
  model: string
  max_tokens_output?: number
  max_tokens_input?: number
  supports: SupportsMap
  conversion?: ConversionMap
  quality_tier?: 'flagship' | 'balanced' | 'economy'
  cost_tier?: 'high' | 'medium' | 'low'
}

export interface ProviderCapabilityMatrix {
  provider: string
  model_pattern: string
  capabilities: Omit<ProviderCapability, 'provider' | 'model'>
}

// Capability matrix - would be loaded from provider-capability-matrix-v1.md
const CAPABILITY_MATRIX: ProviderCapabilityMatrix[] = [
  {
    provider: 'anthropic',
    model_pattern: '^claude-opus-4-.*',
    capabilities: {
      max_tokens_output: 200000,
      max_tokens_input: 200000,
      supports: {
        text_input: true,
        text_output: true,
        streaming: true,
        tool_use: true,
        parallel_tool_use: true,
        structured_output: true,
        json_mode: true,
        thinking: true,
        prompt_cache: true,
        system_prompt: true,
        image_input: true,
        image_output: false,
        audio_input: false,
        audio_output: false,
        file_input: true,
        computer_use: true,
        long_context: true
      },
      conversion: {
        from_anthropic_canonical: true,
        tool_schema: 'native',
        image_input: 'base64',
        thinking: 'native',
        cache_control: 'anthropic'
      },
      quality_tier: 'flagship',
      cost_tier: 'high'
    }
  },
  {
    provider: 'anthropic',
    model_pattern: '^claude-sonnet-4-.*',
    capabilities: {
      max_tokens_output: 200000,
      max_tokens_input: 200000,
      supports: {
        text_input: true,
        text_output: true,
        streaming: true,
        tool_use: true,
        parallel_tool_use: true,
        structured_output: true,
        json_mode: true,
        thinking: true,
        prompt_cache: true,
        system_prompt: true,
        image_input: true,
        image_output: false,
        audio_input: false,
        audio_output: false,
        file_input: true,
        computer_use: true,
        long_context: true
      },
      conversion: {
        from_anthropic_canonical: true,
        tool_schema: 'native',
        image_input: 'base64',
        thinking: 'native',
        cache_control: 'anthropic'
      },
      quality_tier: 'balanced',
      cost_tier: 'medium'
    }
  },
  {
    provider: 'anthropic',
    model_pattern: '^claude-haiku-4-.*',
    capabilities: {
      max_tokens_output: 200000,
      max_tokens_input: 200000,
      supports: {
        text_input: true,
        text_output: true,
        streaming: true,
        tool_use: true,
        parallel_tool_use: true,
        structured_output: true,
        json_mode: true,
        thinking: false,
        prompt_cache: true,
        system_prompt: true,
        image_input: true,
        image_output: false,
        audio_input: false,
        audio_output: false,
        file_input: true,
        computer_use: false,
        long_context: true
      },
      conversion: {
        from_anthropic_canonical: true,
        tool_schema: 'native',
        image_input: 'base64',
        thinking: 'none',
        cache_control: 'anthropic'
      },
      quality_tier: 'economy',
      cost_tier: 'low'
    }
  },
  {
    provider: 'openai',
    model_pattern: '^gpt-5-.*',
    capabilities: {
      max_tokens_output: 128000,
      max_tokens_input: 128000,
      supports: {
        text_input: true,
        text_output: true,
        streaming: true,
        tool_use: true,
        parallel_tool_use: true,
        structured_output: true,
        json_mode: true,
        thinking: true,
        prompt_cache: true,
        system_prompt: true,
        image_input: true,
        image_output: false,
        audio_input: true,
        audio_output: true,
        file_input: true,
        computer_use: false,
        long_context: true
      },
      conversion: {
        from_anthropic_canonical: true,
        tool_schema: 'native',
        image_input: 'url',
        thinking: 'native',
        cache_control: 'openai'
      },
      quality_tier: 'flagship',
      cost_tier: 'high'
    }
  },
  {
    provider: 'openai',
    model_pattern: '^gpt-4[ot]-.*',
    capabilities: {
      max_tokens_output: 128000,
      max_tokens_input: 128000,
      supports: {
        text_input: true,
        text_output: true,
        streaming: true,
        tool_use: true,
        parallel_tool_use: true,
        structured_output: true,
        json_mode: true,
        thinking: false,
        prompt_cache: false,
        system_prompt: true,
        image_input: true,
        image_output: false,
        audio_input: false,
        audio_output: false,
        file_input: true,
        computer_use: false,
        long_context: true
      },
      conversion: {
        from_anthropic_canonical: true,
        tool_schema: 'native',
        image_input: 'url',
        thinking: 'none',
        cache_control: 'openai'
      },
      quality_tier: 'balanced',
      cost_tier: 'medium'
    }
  },
  {
    provider: 'openai-compatible',
    model_pattern: '.*',
    capabilities: {
      // Defaults for compatible providers - actual capability varies
      max_tokens_output: 4096,
      max_tokens_input: 128000,
      supports: {
        text_input: true,
        text_output: true,
        streaming: true,
        tool_use: true,
        parallel_tool_use: false,
        structured_output: false,
        json_mode: true,
        thinking: false,
        prompt_cache: false,
        system_prompt: true,
        image_input: false,
        image_output: false,
        audio_input: false,
        audio_output: false,
        file_input: false,
        computer_use: false,
        long_context: false
      },
      conversion: {
        from_anthropic_canonical: true,
        tool_schema: 'emulated',
        image_input: 'none',
        thinking: 'none',
        cache_control: 'none'
      },
      quality_tier: 'economy',
      cost_tier: 'low'
    }
  },
  {
    provider: 'glm',
    model_pattern: '^glm-5-.*',
    capabilities: {
      max_tokens_output: 128000,
      max_tokens_input: 128000,
      supports: {
        text_input: true,
        text_output: true,
        streaming: true,
        tool_use: true,
        parallel_tool_use: false,
        structured_output: true,
        json_mode: true,
        thinking: true,
        prompt_cache: false,
        system_prompt: true,
        image_input: true,
        image_output: false,
        audio_input: false,
        audio_output: false,
        file_input: true,
        computer_use: false,
        long_context: true
      },
      conversion: {
        from_anthropic_canonical: true,
        tool_schema: 'emulated',
        image_input: 'url',
        thinking: 'emulated',
        cache_control: 'none'
      },
      quality_tier: 'balanced',
      cost_tier: 'medium'
    }
  }
]

export class CapabilityMatrixRegistry {
  private matrix: ProviderCapabilityMatrix[]

  constructor(matrix?: ProviderCapabilityMatrix[]) {
    this.matrix = matrix || CAPABILITY_MATRIX
  }

  /**
   * Look up capabilities for a specific provider/model.
   */
  lookup(provider: string, model: string): ProviderCapability | undefined {
    // Find matching entry
    for (const entry of this.matrix) {
      if (entry.provider !== provider) continue

      const regex = new RegExp(entry.model_pattern)
      if (regex.test(model)) {
        return {
          provider,
          model,
          ...entry.capabilities
        }
      }
    }

    return undefined
  }

  /**
   * List all models for a provider.
   */
  list_models(provider: string): string[] {
    const models: string[] = []

    for (const entry of this.matrix) {
      if (entry.provider === provider) {
        // Extract example model name from pattern
        const example = entry.model_pattern.replace(/^\^|\$.*$/g, '')
        models.push(example || entry.model_pattern)
      }
    }

    return models
  }

  /**
   * Check if a provider/model supports a specific capability.
   * Queries the nested `supports` object.
   */
  supports(provider: string, model: string, capability: keyof SupportsMap): boolean {
    const caps = this.lookup(provider, model)
    if (!caps) return false

    return caps.supports[capability] === true
  }

  /**
   * Get the best model for a set of requirements.
   */
  find_best(
    provider: string,
    requirements: {
      min_output_tokens?: number
      thinking?: boolean
      tool_use?: boolean
    }
  ): string | undefined {
    const entries = this.matrix.filter(e => e.provider === provider)

    for (const entry of entries) {
      const caps = entry.capabilities

      if (requirements.min_output_tokens && (!caps.max_tokens_output || caps.max_tokens_output < requirements.min_output_tokens)) {
        continue
      }

      if (requirements.thinking && !caps.supports.thinking) {
        continue
      }

      if (requirements.tool_use && !caps.supports.tool_use) {
        continue
      }

      // Return first matching model pattern
      return entry.model_pattern.replace(/[\^$]/g, '')
    }

    return undefined
  }
}

export function createCapabilityMatrixRegistry(): CapabilityMatrixRegistry {
  return new CapabilityMatrixRegistry()
}
