package cert

import (
	"testing"

	"github.com/tidbcloud/infra-provider/pkg/consts"
	"github.com/tidbcloud/infra-provider/pkg/namer"
)

// TestTiDBClientCertShortLived pins the behavior of the short-lived feature for
// the tidb-client certificate:
//   - with shortLived=false (the default / existing code path) the certificate is
//     byte-for-byte the same as before the feature was added: 10-year validity,
//     the standard renew window, and the AWS Private CA issuer;
//   - with shortLived=true only the validity window changes; the issuer (and thus
//     the CA a MySQL client verifies against) is unchanged.
func TestTiDBClientCertShortLived(t *testing.T) {
	n := namer.NewNamer()
	pcaIssuer := getTiDBServerIssuerRef(false)

	def := TiDBClientCert(n, false)
	if got := def.Spec.Duration.Duration; got != consts.CertificateDuration {
		t.Fatalf("default duration = %v, want %v (existing behavior must be unchanged)", got, consts.CertificateDuration)
	}
	if got := def.Spec.RenewBefore.Duration; got != consts.RenewBefore {
		t.Fatalf("default renewBefore = %v, want %v (existing behavior must be unchanged)", got, consts.RenewBefore)
	}
	if def.Spec.IssuerRef != pcaIssuer {
		t.Fatalf("default issuer = %+v, want the AWS Private CA issuer %+v", def.Spec.IssuerRef, pcaIssuer)
	}

	short := TiDBClientCert(n, true)
	if got := short.Spec.Duration.Duration; got != consts.ShortLivedComponentCertDuration {
		t.Fatalf("short-lived duration = %v, want %v", got, consts.ShortLivedComponentCertDuration)
	}
	if got := short.Spec.RenewBefore.Duration; got != consts.ShortLivedComponentCertRenewBefore {
		t.Fatalf("short-lived renewBefore = %v, want %v", got, consts.ShortLivedComponentCertRenewBefore)
	}
	// The issuer must be identical whether or not the cert is short-lived: this is
	// what keeps the CA a MySQL client verifies against unchanged.
	if short.Spec.IssuerRef != pcaIssuer {
		t.Fatalf("short-lived issuer = %+v, want the AWS Private CA issuer %+v (issuer must not change)", short.Spec.IssuerRef, pcaIssuer)
	}

	// Nothing other than the validity window may differ between the two.
	if def.Name != short.Name ||
		def.Spec.SecretName != short.Spec.SecretName ||
		def.Spec.CommonName != short.Spec.CommonName {
		t.Fatalf("short-lived flag changed more than the certificate validity window")
	}
}

// TestTiDBServerCertShortLived pins the same guarantee for the tidb-server
// certificate across both issuer choices (selfSigned true/false): the shortLived
// flag only shortens the validity window and never changes the issuer, so an
// existing cluster (shortLived=false) keeps its exact behavior.
func TestTiDBServerCertShortLived(t *testing.T) {
	n := namer.NewNamer()

	for _, selfSigned := range []bool{false, true} {
		wantIssuer := getTiDBServerIssuerRef(selfSigned)

		def := TiDBServerCert(n, false, selfSigned, false)
		if def.Spec.Duration.Duration != consts.CertificateDuration ||
			def.Spec.RenewBefore.Duration != consts.RenewBefore {
			t.Fatalf("selfSigned=%v: default validity changed (existing behavior must be unchanged)", selfSigned)
		}
		if def.Spec.IssuerRef != wantIssuer {
			t.Fatalf("selfSigned=%v: default issuer = %+v, want %+v", selfSigned, def.Spec.IssuerRef, wantIssuer)
		}

		short := TiDBServerCert(n, false, selfSigned, true)
		if short.Spec.Duration.Duration != consts.ShortLivedComponentCertDuration ||
			short.Spec.RenewBefore.Duration != consts.ShortLivedComponentCertRenewBefore {
			t.Fatalf("selfSigned=%v: short-lived validity is wrong", selfSigned)
		}
		if short.Spec.IssuerRef != wantIssuer {
			t.Fatalf("selfSigned=%v: short-lived issuer = %+v changed, want %+v (must match non-short-lived)", selfSigned, short.Spec.IssuerRef, wantIssuer)
		}
	}
}
