//
//  FoundationModelTools.stencil
//  Sourcery template for generating FoundationModels Tool adapters
//
//  Usage: Annotate your InferenceTool with:
//    // sourcery: inferenceToolAdapter
//    // sourcery: toolArgumentsType = "YourArgumentsType"
//    // sourcery: toolOutputType = "YourOutputType"
//

import Foundation
import InferenceKit

#if canImport(FoundationModels)
import FoundationModels

// MARK: - FoundationModels Tool Adapters
// Auto-generated adapters that wrap InferenceTool and implement FM's Tool protocol

{% for type in types.structs where type.annotations.inferenceToolAdapter %}
{% set argsType %}{{ type.annotations.toolArgumentsType }}{% endset %}
{% set outputType %}{{ type.annotations.toolOutputType }}{% endset %}
/// FoundationModels adapter for `{{ type.name }}`
@available(macOS 26.0, iOS 26.0, *)
public struct FoundationModels{{ type.name }}: Tool {
    public let wrapped: {{ type.name }}
    
    public typealias Arguments = ToolGenerable{{ argsType }}
    public typealias Output = ToolGenerable{{ outputType }}
    
    public var name: String { wrapped.name }
    public var description: String { wrapped.description }
    
    public init(wrapped: {{ type.name }}) {
        self.wrapped = wrapped
    }
    
    public func call(arguments: Arguments) async throws -> Output {
        // Convert ToolGenerable arguments to plain arguments
        let plainArgs = {{ argsType }}(
{% for argType in types.structs where argType.name == argsType %}{% for variable in argType.storedVariables %}
            {{ variable.name }}: arguments.{{ variable.name }}{% if not forloop.last %},{% endif %}
{% endfor %}{% endfor %}
        )
        
        // Call the wrapped tool
        let plainResult = try await wrapped.call(arguments: plainArgs)
        
        // Convert plain result to ToolGenerable result
        return ToolGenerable{{ outputType }}(
{% for outType in types.structs where outType.name == outputType %}{% for variable in outType.storedVariables %}
            {{ variable.name }}: plainResult.{{ variable.name }}{% if not forloop.last %},{% endif %}
{% endfor %}{% endfor %}
        )
    }
}

// Extension to make the tool convertible
@available(macOS 26.0, iOS 26.0, *)
extension {{ type.name }}: FoundationModelsConvertibleTool {
    public func toFoundationModelsTool() -> any Tool {
        return FoundationModels{{ type.name }}(wrapped: self)
    }
}

{% endfor %}
#endif
