package main

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/anthropics/anthropic-sdk-go"
	"github.com/invopop/jsonschema"
)

// Example struct with various field types and constraints
type WeatherQuery struct {
	Location    string   `json:"location" jsonschema:"title=Location,description=The city and state e.g. San Francisco CA"`
	Units       string   `json:"units,omitempty" jsonschema:"enum=celsius,enum=fahrenheit,default=fahrenheit"`
	Days        int      `json:"days" jsonschema:"minimum=1,maximum=7,description=Number of days to forecast"`
	IncludeWind bool     `json:"include_wind,omitempty"`
	Details     []string `json:"details,omitempty" jsonschema:"minItems=1,maxItems=5"`
}

func main() {
	schemaMap := generateJSONSchema(&WeatherQuery{})

	fmt.Println("schema generated by invopop/jsonschema:")
	printJSON(schemaMap)

	client := anthropic.NewClient()

	messages := []anthropic.BetaMessageParam{
		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What's the weather like in San Francisco for the next 3 days? Include wind information.")),
	}

	msg, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
		Model:        anthropic.Model("claude-sonnet-4-5"),
		MaxTokens:    1024,
		Messages:     messages,
		OutputFormat: anthropic.BetaJSONSchemaOutputFormat(schemaMap),
		Betas:        []anthropic.AnthropicBeta{"structured-outputs-2025-11-13"},
	})

	if err != nil {
		fmt.Printf("Error calling API: %v\n", err)
		return
	}

	fmt.Println("\nAPI Response:")
	for _, block := range msg.Content {
		switch v := block.AsAny().(type) {
		case anthropic.BetaTextBlock:
			fmt.Printf("Text: %s\n", v.Text)
		case anthropic.BetaToolUseBlock:
			fmt.Printf("Tool use: %s\n", v.Name)
			fmt.Printf("Input: %s\n", v.JSON.Input.Raw())
		}
	}

}

func generateJSONSchema(t any) map[string]any {
	reflector := jsonschema.Reflector{
		AllowAdditionalProperties: false,
		DoNotReference:            true,
	}
	schema := reflector.Reflect(t)
	schemaBytes, err := json.Marshal(schema)
	if err != nil {
		panic(err)
	}
	var schemaMap map[string]any
	if err := json.Unmarshal(schemaBytes, &schemaMap); err != nil {
		panic(err)
	}
	return schemaMap

}

func printJSON(v any) {
	b, err := json.MarshalIndent(v, "", "  ")
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Println(string(b))
}
