package insightsv1_test

import (
	"testing"
	"time"

	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/known/timestamppb"

	insightsv1 "github.com/tetrateio/agentrouter-go/genapi/api/tars/insights/v1"
)

// createSampleRequestLog creates a realistic RequestLog for benchmarking
func createSampleRequestLog() *insightsv1.RequestLog {
	return &insightsv1.RequestLog{
		Id:                        "req-123456789",
		Timestamp:                 timestamppb.New(time.Now()),
		UserId:                    "user-abc123",
		ApiKeyId:                  "key-xyz789",
		ApiKeyPrefix:              "sk-ant",
		ApiKeyHash:                "hash123456",
		ApiKeyAddress:             "192.168.1.1",
		ApiKeyName:                "production-key",
		ModelName:                 "claude-sonnet-4-5",
		InputTokens:               1500,
		OutputTokens:              800,
		Status:                    "success",
		StatusCode:                200,
		UpstreamDurationMs:        2500,
		DurationMs:                2550,
		RequestId:                 "req-123456789",
		CreatedAt:                 timestamppb.New(time.Now()),
		InputTokensCost:           "0.0045",
		OutputTokensCost:          "0.0120",
		InputTokensCostBeforeFee:  "0.0040",
		OutputTokensCostBeforeFee: "0.0100",
		UseObjectStorage:          false,
	}
}

// createSampleQueryResponse creates a realistic QueryRequestLogsResponse
func createSampleQueryResponse() *insightsv1.QueryRequestLogsResponse {
	logs := make([]*insightsv1.RequestLog, 50)
	for i := 0; i < 50; i++ {
		logs[i] = createSampleRequestLog()
	}
	return &insightsv1.QueryRequestLogsResponse{
		Logs:          logs,
		NextPageToken: "next-page-token-abc",
		TotalCount:    1000,
	}
}

// Benchmark standard proto.Marshal/Unmarshal for RequestLog
func BenchmarkRequestLog_StandardProto(b *testing.B) {
	msg := createSampleRequestLog()
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		data, err := proto.Marshal(msg)
		if err != nil {
			b.Fatal(err)
		}
		newMsg := &insightsv1.RequestLog{}
		if err := proto.Unmarshal(data, newMsg); err != nil {
			b.Fatal(err)
		}
	}
}

// Benchmark vtprotobuf MarshalVT/UnmarshalVT for RequestLog
func BenchmarkRequestLog_VTProto(b *testing.B) {
	msg := createSampleRequestLog()
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		data, err := msg.MarshalVT()
		if err != nil {
			b.Fatal(err)
		}
		newMsg := &insightsv1.RequestLog{}
		if err := newMsg.UnmarshalVT(data); err != nil {
			b.Fatal(err)
		}
	}
}

// Benchmark standard proto.Marshal/Unmarshal for QueryResponse (50 logs)
func BenchmarkQueryResponse_StandardProto(b *testing.B) {
	msg := createSampleQueryResponse()
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		data, err := proto.Marshal(msg)
		if err != nil {
			b.Fatal(err)
		}
		newMsg := &insightsv1.QueryRequestLogsResponse{}
		if err := proto.Unmarshal(data, newMsg); err != nil {
			b.Fatal(err)
		}
	}
}

// Benchmark vtprotobuf for QueryResponse (50 logs)
func BenchmarkQueryResponse_VTProto(b *testing.B) {
	msg := createSampleQueryResponse()
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		data, err := msg.MarshalVT()
		if err != nil {
			b.Fatal(err)
		}
		newMsg := &insightsv1.QueryRequestLogsResponse{}
		if err := newMsg.UnmarshalVT(data); err != nil {
			b.Fatal(err)
		}
	}
}

// Benchmark just marshaling for RequestLog
func BenchmarkRequestLog_Marshal_StandardProto(b *testing.B) {
	msg := createSampleRequestLog()
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_, err := proto.Marshal(msg)
		if err != nil {
			b.Fatal(err)
		}
	}
}

func BenchmarkRequestLog_Marshal_VTProto(b *testing.B) {
	msg := createSampleRequestLog()
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_, err := msg.MarshalVT()
		if err != nil {
			b.Fatal(err)
		}
	}
}

// Benchmark just unmarshaling for RequestLog
func BenchmarkRequestLog_Unmarshal_StandardProto(b *testing.B) {
	msg := createSampleRequestLog()
	data, _ := proto.Marshal(msg)
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		newMsg := &insightsv1.RequestLog{}
		if err := proto.Unmarshal(data, newMsg); err != nil {
			b.Fatal(err)
		}
	}
}

func BenchmarkRequestLog_Unmarshal_VTProto(b *testing.B) {
	msg := createSampleRequestLog()
	data, _ := msg.MarshalVT()
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		newMsg := &insightsv1.RequestLog{}
		if err := newMsg.UnmarshalVT(data); err != nil {
			b.Fatal(err)
		}
	}
}

// Benchmark SizeVT method
func BenchmarkRequestLog_Size_StandardProto(b *testing.B) {
	msg := createSampleRequestLog()
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_ = proto.Size(msg)
	}
}

func BenchmarkRequestLog_Size_VTProto(b *testing.B) {
	msg := createSampleRequestLog()
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		_ = msg.SizeVT()
	}
}
