// generated by claude sonnet 4.6
package integration_test

import (
	"context"
	"fmt"
	"os"
	"testing"
	"time"

	"github.com/pardnchiu/agenvoy/internal/agents/provider"
	"github.com/pardnchiu/agenvoy/internal/agents/provider/claude"
	"github.com/pardnchiu/agenvoy/internal/agents/provider/copilot"
	"github.com/pardnchiu/agenvoy/internal/agents/provider/gemini"
	"github.com/pardnchiu/agenvoy/internal/agents/provider/nvidia"
	"github.com/pardnchiu/agenvoy/internal/agents/provider/openai"
	agentTypes "github.com/pardnchiu/agenvoy/internal/agents/types"
	"github.com/pardnchiu/agenvoy/internal/filesystem"
	"github.com/pardnchiu/go-pkg/filesystem/keychain"
)

func TestMain(m *testing.M) {
	if err := filesystem.Init(); err != nil {
		fmt.Fprintf(os.Stderr, "filesystem.Init: %v\n", err)
		os.Exit(1)
	}
	os.Exit(m.Run())
}

var minimalMessages = []agentTypes.Message{
	{Role: "user", Content: "say ok"},
}

func assertSend(t *testing.T, send func(context.Context) (*agentTypes.Output, error)) {
	t.Helper()
	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()
	out, err := send(ctx)
	if err != nil {
		t.Fatalf("Send: %v", err)
	}
	if len(out.Choices) == 0 {
		t.Fatal("no choices")
	}
	content, _ := out.Choices[0].Message.Content.(string)
	if content == "" {
		t.Fatal("empty content")
	}
	t.Logf("response: %s", content)
}

func TestProviderClaude(t *testing.T) {
	if keychain.Get("ANTHROPIC_API_KEY") == "" {
		t.Skip("ANTHROPIC_API_KEY not set")
	}
	for model := range provider.Models("claude") {
		model := model
		t.Run(model, func(t *testing.T) {
			t.Parallel()
			agent, err := claude.New(fmt.Sprintf("claude@%s", model))
			if err != nil {
				t.Fatalf("claude.New: %v", err)
			}
			assertSend(t, func(ctx context.Context) (*agentTypes.Output, error) {
				return agent.Send(ctx, minimalMessages, nil)
			})
		})
	}
}

func TestProviderOpenAI(t *testing.T) {
	if keychain.Get("OPENAI_API_KEY") == "" {
		t.Skip("OPENAI_API_KEY not set")
	}
	for model := range provider.Models("openai") {
		model := model
		t.Run(model, func(t *testing.T) {
			t.Parallel()
			agent, err := openai.New(fmt.Sprintf("openai@%s", model))
			if err != nil {
				t.Fatalf("openai.New: %v", err)
			}
			assertSend(t, func(ctx context.Context) (*agentTypes.Output, error) {
				return agent.Send(ctx, minimalMessages, nil)
			})
		})
	}
}

func TestProviderGemini(t *testing.T) {
	if keychain.Get("GEMINI_API_KEY") == "" {
		t.Skip("GEMINI_API_KEY not set")
	}
	for model := range provider.Models("gemini") {
		model := model
		t.Run(model, func(t *testing.T) {
			t.Parallel()
			agent, err := gemini.New(fmt.Sprintf("gemini@%s", model))
			if err != nil {
				t.Fatalf("gemini.New: %v", err)
			}
			assertSend(t, func(ctx context.Context) (*agentTypes.Output, error) {
				return agent.Send(ctx, minimalMessages, nil)
			})
		})
	}
}

func TestProviderNvidia(t *testing.T) {
	if keychain.Get("NVIDIA_API_KEY") == "" {
		t.Skip("NVIDIA_API_KEY not set")
	}
	for model := range provider.Models("nvidia") {
		model := model
		t.Run(model, func(t *testing.T) {
			t.Parallel()
			agent, err := nvidia.New(fmt.Sprintf("nvidia@%s", model))
			if err != nil {
				t.Fatalf("nvidia.New: %v", err)
			}
			assertSend(t, func(ctx context.Context) (*agentTypes.Output, error) {
				return agent.Send(ctx, minimalMessages, nil)
			})
		})
	}
}

func TestProviderCopilot(t *testing.T) {
	if keychain.Get("agenvoy.copilot.token") == "" {
		t.Skip("agenvoy.copilot.token not in keychain, run `agen model add` to authenticate")
	}
	for model := range provider.Models("copilot") {
		model := model
		t.Run(model, func(t *testing.T) {
			t.Parallel()
			agent, err := copilot.New(fmt.Sprintf("copilot@%s", model))
			if err != nil {
				t.Fatalf("copilot.New: %v", err)
			}
			assertSend(t, func(ctx context.Context) (*agentTypes.Output, error) {
				return agent.Send(ctx, minimalMessages, nil)
			})
		})
	}
}
