package cluster

import (
	"testing"
	"time"

	rpproto "github.com/tidbcloud/dataflow-service/idl/pbgen/proto/replay"

	clusterapi "github.com/tidbcloud/devops/api/cluster"
)

func TestTrafficReplayConverterReplayFromPBMatchesMainNilStatusAndTimestampBehavior(t *testing.T) {
	got := TrafficReplayConverter{}.ReplayFromPB(&rpproto.Replay{
		ReplayId: "replay-1",
	})

	if got == nil {
		t.Fatal("expected replay")
	}
	if got.ReplayID != "replay-1" {
		t.Fatalf("unexpected replay id: %s", got.ReplayID)
	}
	if got.ReplayStatus == nil {
		t.Fatal("expected non-nil replay status")
	}
	if !got.CreatedAt.Equal(time.Unix(0, 0).UTC()) {
		t.Fatalf("expected epoch created_at, got %s", got.CreatedAt)
	}
	if !got.UpdatedAt.Equal(time.Unix(0, 0).UTC()) {
		t.Fatalf("expected epoch updated_at, got %s", got.UpdatedAt)
	}
	if !got.ReplayStatus.LastUpdateTime.Equal(time.Unix(0, 0).UTC()) {
		t.Fatalf("expected epoch replay status last_update_time, got %s", got.ReplayStatus.LastUpdateTime)
	}
}

func TestTrafficReplayConverterReplaySpecToPBConvertsSourceAliyunCredential(t *testing.T) {
	got, err := TrafficReplayConverter{}.ReplaySpecToPB(&clusterapi.TrafficReplaySpec{
		SourceAuditCredential: &clusterapi.TrafficReplayAuditLogAddr{
			Aliyun: &clusterapi.TrafficReplayAliyunAuditLog{
				BucketURL:       "oss://bucket/path",
				AccessKeyID:     "ak",
				SecretAccessKey: "sk",
			},
		},
	})
	if err != nil {
		t.Fatalf("ReplaySpecToPB() error = %v", err)
	}

	aliyun := got.GetSourceAuditCredential().GetAliyun()
	if aliyun == nil {
		t.Fatal("expected aliyun source audit credential")
	}
	if aliyun.GetBucketUrl() != "oss://bucket/path" {
		t.Fatalf("unexpected bucket url: %s", aliyun.GetBucketUrl())
	}
	if aliyun.GetAccessKeyId() != "ak" {
		t.Fatalf("unexpected access key id: %s", aliyun.GetAccessKeyId())
	}
	if aliyun.GetSecretAccessKey() != "sk" {
		t.Fatalf("unexpected secret access key: %s", aliyun.GetSecretAccessKey())
	}
}

func TestTrafficReplayConverterAuditLogAddrFromPBConvertsAliyunCredential(t *testing.T) {
	got := TrafficReplayConverter{}.AuditLogAddrFromPB(&rpproto.AuditLogAddr{
		Storage: &rpproto.AuditLogAddr_Aliyun{
			Aliyun: &rpproto.AliyunAuditLog{
				BucketUrl:       "oss://bucket/path",
				AccessKeyId:     "ak",
				SecretAccessKey: "sk",
			},
		},
	})

	if got == nil || got.Aliyun == nil {
		t.Fatalf("expected aliyun audit log addr, got %#v", got)
	}
	if got.Aliyun.BucketURL != "oss://bucket/path" {
		t.Fatalf("unexpected bucket url: %s", got.Aliyun.BucketURL)
	}
	if got.Aliyun.AccessKeyID != "ak" {
		t.Fatalf("unexpected access key id: %s", got.Aliyun.AccessKeyID)
	}
	if got.Aliyun.SecretAccessKey != "sk" {
		t.Fatalf("unexpected secret access key: %s", got.Aliyun.SecretAccessKey)
	}
}

func TestTrafficReplayConverterReplaySpecToPBKeepsMainOverwriteBehaviorForMultipleAuditLogProviders(t *testing.T) {
	got, err := TrafficReplayConverter{}.ReplaySpecToPB(&clusterapi.TrafficReplaySpec{
		SourceAuditCredential: &clusterapi.TrafficReplayAuditLogAddr{
			AWS: &clusterapi.TrafficReplayAWSAuditLog{
				S3Url: "s3://bucket/path",
			},
			Aliyun: &clusterapi.TrafficReplayAliyunAuditLog{
				BucketURL:       "oss://bucket/path",
				AccessKeyID:     "ak",
				SecretAccessKey: "sk",
			},
		},
	})
	if err != nil {
		t.Fatalf("ReplaySpecToPB() error = %v", err)
	}

	aliyun := got.GetSourceAuditCredential().GetAliyun()
	if aliyun == nil {
		t.Fatal("expected aliyun source audit credential")
	}
	if aliyun.GetBucketUrl() != "oss://bucket/path" {
		t.Fatalf("unexpected bucket url: %s", aliyun.GetBucketUrl())
	}
}

func TestTrafficReplayConverterReplaySpecToPBParsesSnakeCaseAliyunReplayTasks(t *testing.T) {
	got, err := TrafficReplayConverter{}.ReplaySpecToPB(&clusterapi.TrafficReplaySpec{
		ReplayTasks: `[{
			"name": "task-1",
			"data_source": {
				"source_audit_log_addrs": [{
					"aliyun": {
						"bucket_url": "oss://bucket/path",
						"access_key_id": "ak",
						"secret_access_key": "sk"
					}
				}]
			},
			"data_target": {
				"endpoint": "tidb.example.com:4000"
			}
		}]`,
	})
	if err != nil {
		t.Fatalf("ReplaySpecToPB() error = %v", err)
	}

	if len(got.GetReplayTasks()) != 1 {
		t.Fatalf("expected one replay task, got %d", len(got.GetReplayTasks()))
	}
	addrs := got.GetReplayTasks()[0].GetDataSource().GetSourceAuditLogAddrs()
	if len(addrs) != 1 {
		t.Fatalf("expected one audit log addr, got %d", len(addrs))
	}
	aliyun := addrs[0].GetAliyun()
	if aliyun == nil {
		t.Fatal("expected aliyun audit log addr")
	}
	if aliyun.GetBucketUrl() != "oss://bucket/path" {
		t.Fatalf("unexpected bucket url: %s", aliyun.GetBucketUrl())
	}
}
