package integration

import (
	"bytes"
	"io"
	"os"
	"testing"

	"github.com/tidbcloud/aws-shared-provider/tools/cloud-instances/provider"
	"github.com/tidbcloud/aws-shared-provider/tools/cloud-instances/query"
	"github.com/tidbcloud/aws-shared-provider/tools/cloud-instances/types"
)

type integrationStubProvider struct{}

func (p *integrationStubProvider) DownloadRaw(region string) (*provider.RawBundle, error) {
	return &provider.RawBundle{
		Provider: "stub",
		Region:   region,
		Parts: []provider.RawPart{
			{Scope: region, Name: "data", Data: []byte(region)},
		},
	}, nil
}

func (p *integrationStubProvider) ParseRaw(raw *provider.RawBundle) (*types.UnifiedData, error) {
	ud := types.NewUnifiedData("stub")
	ud.Instances[raw.Region] = []types.UnifiedInstance{{
		Provider:     "stub",
		InstanceType: "stub.type",
		VCPU:         "2",
		Memory:       "1 GiB",
		Price:        0.01,
		Currency:     "USD",
		Location:     "Test Region",
		Region:       raw.Region,
	}}
	return ud, nil
}

func (p *integrationStubProvider) GetRegions() map[string]string {
	return map[string]string{"test-region": "Test Region"}
}

func (p *integrationStubProvider) IsValidRegion(regionID string) bool {
	return regionID == "test-region"
}

func (p *integrationStubProvider) GetRegionName(regionID string) string {
	return "Test Region"
}

func (p *integrationStubProvider) GetCacheFileName(region string) string {
	return "stub_" + region + ".json"
}

func (p *integrationStubProvider) GetProviderName() string {
	return "stub"
}

func TestIntegrationQueryAndOutput(t *testing.T) {
	cacheDir := t.TempDir()
	engine := query.NewQueryEngine(cacheDir)
	engine.Providers = map[string]provider.CloudProvider{"stub": &integrationStubProvider{}}

	opts := query.FilterOptions{
		Provider:     "stub",
		Regions:      []string{"test-region"},
		OutputFormat: "json",
		OutputStyle:  "compact",
		ShowDetails:  true,
	}

	if err := engine.Download(opts); err != nil {
		t.Fatalf("download: %v", err)
	}

	oldStdout := os.Stdout
	r, w, _ := os.Pipe()
	os.Stdout = w

	err := engine.QueryAndOutput(opts)
	w.Close()
	os.Stdout = oldStdout
	if err != nil {
		t.Fatalf("query output: %v", err)
	}

	out, _ := io.ReadAll(r)
	if !bytes.Contains(out, []byte("\"instance_type\"")) {
		t.Fatalf("expected json output to contain instance_type")
	}
}
