package config

import (
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"log"
	"os"

	"sigs.k8s.io/yaml"
)

type SelfSignedCAConfig struct {
	// if it's nil, skip get TiDB Server self-signed ca data
	TiDBServerSelfSignedCAPath string `json:"tidbServerSelfSignedCAPath"`
	tidbServerSelfSignedCAData map[string][]byte
}

func (c *SelfSignedCAConfig) GetTiDBServerSelfSignedCAData() map[string][]byte {
	return c.tidbServerSelfSignedCAData
}

func (c *SelfSignedCAConfig) InitTiDBServerSelfSignedCAData() {
	// 	tls.crt: <base64-encoded>
	// 	tls.key: <base64-encoded>
	if c.TiDBServerSelfSignedCAPath != "" {
		data, err := os.ReadFile(c.TiDBServerSelfSignedCAPath)
		if err != nil {
			panic(err)
		}

		var tlsData map[string][]byte
		err = yaml.Unmarshal(data, &tlsData)
		if err != nil {
			panic(err)
		}

		if err := verifyCertificate(tlsData["ca.crt"]); err != nil {
			log.Panicf("failed to verify certificate: %v", err)
		} else {
			log.Printf("certificate verified")
		}

		if err := verifyCertificate(tlsData["tls.crt"]); err != nil {
			log.Panicf("failed to verify TLS certificate: %v", err)
		} else {
			log.Printf("TLS certificate verified")
		}

		if err := verifyPrivateKey(tlsData["tls.key"]); err != nil {
			log.Panicf("failed to verify TLS private key: %v", err)
		} else {
			log.Printf("TLS private key verified")
		}

		c.tidbServerSelfSignedCAData = tlsData
	}
	// enforce to set TiDBServerSelfSignedCAPath when enable self-signed tidb clusterissuer by default
	// else {
	// 	panic("TiDBServerSelfSignedCAPath is empty")
	// }
}

func verifyCertificate(certPEM []byte) error {
	block, _ := pem.Decode(certPEM)
	if block == nil || block.Type != "CERTIFICATE" {
		return fmt.Errorf("failed to decode PEM block containing certificate")
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return err
	}

	// Verify the certificate (this is a basic check, you might need to add more checks)
	opts := x509.VerifyOptions{
		Roots: x509.NewCertPool(),
	}
	opts.Roots.AddCert(cert)

	if _, err := cert.Verify(opts); err != nil {
		return fmt.Errorf("failed to verify certificate: %v", err)
	}

	return nil
}

func verifyPrivateKey(keyPEM []byte) error {
	block, _ := pem.Decode(keyPEM)
	if block == nil || block.Type != "RSA PRIVATE KEY" {
		return fmt.Errorf("failed to decode PEM block containing private key")
	}

	_, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return fmt.Errorf("failed to parse private key: %v", err)
	}

	return nil
}
