/**
 * OpenRouter Adapter Integration Test
 *
 * Purpose: Verify OpenRouter adapter works with real API calls
 * Pattern: External API Integration (Pattern 4)
 * Runs in CI: NO (requires OPENROUTER_API_KEY)
 *
 * Prerequisites:
 * - OPENROUTER_API_KEY in .env.development
 *
 * Run locally:
 *   cd packages/core
 *   pnpm vitest run openrouter.integration
 *
 * Note: Tests use models defined in OpenRouterModel type (model-info.ts)
 */

import { describe, it, expect, beforeAll } from 'vitest'
import { createLLMAdapter } from '../server/adapter-factory'
import type { ModelConfig } from '../../model-info'
import type { LLMGenerateRequest } from '../../types'

// Skip by default: real OpenRouter model behavior can change independently of this repo.
const SKIP_TESTS = process.env.RUN_OPENROUTER_INTEGRATION !== 'true' || !process.env.OPENROUTER_API_KEY

describe.skipIf(SKIP_TESTS)('OpenRouter Adapter Integration', () => {
  let apiKey: string

  beforeAll(() => {
    apiKey = process.env.OPENROUTER_API_KEY!
  })

  const createRequest = (prompt: string): LLMGenerateRequest => ({
    messages: [
      { role: 'system', content: 'You are a helpful assistant. Always respond with valid JSON matching the schema.' },
      { role: 'user', content: prompt }
    ],
    responseSchema: {
      type: 'object',
      properties: {
        answer: { type: 'string' },
        confidence: { type: 'number' }
      },
      required: ['answer', 'confidence'],
      additionalProperties: false
    },
    maxOutputTokens: 500
  })

  describe('OpenRouter hosted model', () => {
    it('generates structured output with accurate token counts', async () => {
      const config: ModelConfig = {
        provider: 'openrouter',
        model: 'openrouter/z-ai/glm-5',
        apiKey,
        temperature: 0.7,
        maxOutputTokens: 500
      }

      const adapter = createLLMAdapter(config)
      const request = createRequest('What is the capital of France? Be concise.')

      const response = await adapter.generate<{ answer: string; confidence: number }>(request)

      expect(response.output).toBeDefined()
      expect(response.output.answer).toBeDefined()
      expect(typeof response.output.answer).toBe('string')
      expect(response.output.answer.toLowerCase()).toContain('paris')
      expect(response.usage).toBeDefined()
      expect(response.usage?.inputTokens).toBeGreaterThan(0)
      expect(response.usage?.outputTokens).toBeGreaterThan(0)
      expect(response.usage?.totalTokens).toBe((response.usage?.inputTokens || 0) + (response.usage?.outputTokens || 0))

      // Verify actual cost from OpenRouter usage accounting
      expect(response.cost).toBeDefined()
      expect(typeof response.cost).toBe('number')
      expect(response.cost).toBeGreaterThan(0)
    }, 30000)
  })

  describe('OpenRouter Options', () => {
    it.skip('works with fallback routing option', async () => {
      const config: ModelConfig = {
        provider: 'openrouter',
        model: 'openrouter/deepseek/deepseek-v3.2',
        apiKey,
        temperature: 0.7,
        maxOutputTokens: 500,
        modelOptions: {
          route: 'fallback'
        }
      }

      const adapter = createLLMAdapter(config)
      const request = createRequest('Say hello.')

      const response = await adapter.generate<{ answer: string; confidence: number }>(request)

      // Fallback routing may use models with varying structured output support
      // Verify we get a response, but the model may not always return the exact schema
      expect(response).toBeDefined()
      expect(response.usage).toBeDefined()
    }, 60000)
  })
})
