//
//  AIProviderTests.swift
//  oAITests
//
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
// Copyright (C) 2026 Rune Olsen

import Testing
import Foundation
@testable import Confab

@Suite("ChatResponse / Usage decoding")
struct AIProviderTests {

    @Test("Usage decodes token counts and cache fields from snake_case keys")
    func usageDecodesTokenCounts() throws {
        let json = """
        {
            "prompt_tokens": 100,
            "completion_tokens": 50,
            "total_tokens": 150,
            "cache_creation_input_tokens": 20,
            "cache_read_input_tokens": 10
        }
        """.data(using: .utf8)!
        let usage = try JSONDecoder().decode(ChatResponse.Usage.self, from: json)
        #expect(usage.promptTokens == 100)
        #expect(usage.completionTokens == 50)
        #expect(usage.totalTokens == 150)
        #expect(usage.cacheCreationInputTokens == 20)
        #expect(usage.cacheReadInputTokens == 10)
    }

    @Test("Usage.rawCostUSD is always nil after decoding, even if a matching key were present")
    func usageRawCostNeverDecoded() throws {
        // rawCostUSD has no CodingKeys entry at all -- it's only ever set via the
        // memberwise init, never from API JSON. Confirm decode always yields nil,
        // which is exactly the "$0.0000 cost" regression this guards against.
        let json = """
        {
            "prompt_tokens": 1,
            "completion_tokens": 1,
            "total_tokens": 2,
            "raw_cost_u_s_d": 5.0
        }
        """.data(using: .utf8)!
        let usage = try JSONDecoder().decode(ChatResponse.Usage.self, from: json)
        #expect(usage.rawCostUSD == nil)
    }

    @Test("Usage cache fields are nil when absent from the response")
    func usageMissingCacheFields() throws {
        let json = #"{"prompt_tokens":1,"completion_tokens":1,"total_tokens":2}"#.data(using: .utf8)!
        let usage = try JSONDecoder().decode(ChatResponse.Usage.self, from: json)
        #expect(usage.cacheCreationInputTokens == nil)
        #expect(usage.cacheReadInputTokens == nil)
    }

    @Test("ChatResponse decodes core fields and forces toolCalls/generatedImages to nil")
    func chatResponseDecodesCoreFieldsOnly() throws {
        let json = """
        {
            "id": "resp-1",
            "model": "test-model",
            "content": "hello there",
            "role": "assistant",
            "finishReason": "stop",
            "created": 1700000000
        }
        """.data(using: .utf8)!
        let response = try JSONDecoder().decode(ChatResponse.self, from: json)
        #expect(response.id == "resp-1")
        #expect(response.model == "test-model")
        #expect(response.content == "hello there")
        #expect(response.role == "assistant")
        #expect(response.finishReason == "stop")
        // Not part of CodingKeys -- always nil straight out of decode.
        #expect(response.toolCalls == nil)
        #expect(response.generatedImages == nil)
    }
}
