package certs

import (
	"bytes"
	"crypto"
	"crypto/ed25519"
	"crypto/rand"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"fmt"
	"log"
	"math/big"
	"net"
	"os"
	"path/filepath"
	"time"
)

// Certificate is a higher-level descriptor of an intent to generate a
// certificate and corresponding Ed25519 keypair on disk.
type Certificate struct {
	// uniquer name for this cert, used to calculate filesystem paths.
	name string
	// root directory where all certs are stored.
	root string
	// duration used to determine TimeAfter. If not set, the certificate will
	// never expire.
	duration time.Duration

	kind certificateKind

	// cn is the subject common name that's going to be produced in the X.509
	// certificate.
	cn string
	// o is the subject organziation that's going to be produced in the X.509
	// certificate.
	o string
	// san are the DNS alternate names that are going to be produced in the
	// X.509 certificate.
	san []string
	// ips are the IP alternate names that are going to be produced in the
	// X.509 certificate.
	ips []net.IP

	// issuer, if set, is the certificate that will sign this certificate. If
	// not set, the certificate will be self-signed.
	issuer *Certificate
}

// Paths returns local filesystem paths to the CA certificate, certificate and
// key respectively. If the certificate is self signed, the CA path returned
// will be empty. These files might or might not live on the file system - you
// should first call Ensure to make sure they do.
func (c *Certificate) Paths() (caPath, certPath, keyPath string) {
	if c.issuer != nil {
		caPath = c.issuer.path(fileKindCert)
	}
	certPath = c.path(fileKindCert)
	keyPath = c.path(fileKindKey)
	return
}

type certificateKind string

const (
	kindServer       certificateKind = "server"
	kindClient       certificateKind = "client"
	kindClientServer certificateKind = "client-server"
	kindCA           certificateKind = "ca"
	kindProdvider    certificateKind = "prodvider"
)

type fileKind string

const (
	fileKindKey          fileKind = "key"
	fileKindKeyEncrypted fileKind = "key-encrypted"
	fileKindCert         fileKind = "cert"
)

// path returns the path to the generated fileKind for this Certificate.
func (c *Certificate) path(k fileKind) string {
	switch k {
	case fileKindKeyEncrypted:
		return filepath.Join(c.root, "secrets", "cipher", c.name+".key")
	case fileKindKey:
		return filepath.Join(c.root, "secrets", "plain", c.name+".key")
	case fileKindCert:
		// clustercfg.py compat: CA certs end in .crt, non-CA certs end in .cert.
		// We're keeping this accidental convention to avoid spurious nix rebuilds
		// when migrating.
		//
		// Feel free to fix it if it annoys you.
		extension := ".cert"
		if c.kind == kindCA {
			extension = ".crt"
		}
		return filepath.Join(c.root, "certs", c.name+extension)
	default:
		panic("unexpected file kind type " + k)
	}
}

// ensureKey loads or generates-then-saves the private key for this
// Certificate.
func (c *Certificate) ensureKey() (crypto.Signer, error) {
	path := c.path(fileKindKey)
	_, err := os.Stat(path)
	switch {
	case err == nil:
		return c.loadKey()
	case errors.Is(err, os.ErrNotExist):
		epath := c.path(fileKindKeyEncrypted)
		if _, err = os.Stat(epath); err == nil {
			return nil, fmt.Errorf("plaintext key at %q not found, but exists encrypted at %q - please decrypt using secretstore", path, epath)
		}
		return c.generateKey()
	default:
		return nil, fmt.Errorf("could not read key: %w", err)
	}
}

func (c *Certificate) loadKey() (crypto.Signer, error) {
	path := c.path(fileKindKey)
	bytes, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}
	block, _ := pem.Decode(bytes)
	if block == nil {
		return nil, fmt.Errorf("no PEM block found")
	}
	if block.Type != "PRIVATE KEY" {
		return nil, fmt.Errorf("unexpected PEM block: %q", block.Type)
	}
	key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	if k, ok := key.(ed25519.PrivateKey); ok {
		return k, nil
	}
	return nil, fmt.Errorf("not an ED25519 key")
}

func (c *Certificate) generateKey() (crypto.Signer, error) {
	_, priv, err := ed25519.GenerateKey(rand.Reader)
	if err != nil {
		return nil, err
	}

	pkcs8, err := x509.MarshalPKCS8PrivateKey(priv)
	if err != nil {
		return nil, err
	}

	block := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: pkcs8})
	path := c.path(fileKindKey)
	os.MkdirAll(filepath.Dir(path), 0700)
	log.Printf("Saving %s key to %s ...", c.name, path)
	if err := os.WriteFile(path, block, 0600); err != nil {
		return nil, err
	}

	return priv, nil
}

// ensureCert loads or generates-then-saves the X.509 certificate for the
// Certificate.
func (c *Certificate) ensureCert() (*x509.Certificate, error) {
	path := c.path(fileKindCert)
	_, err := os.Stat(path)
	switch {
	case err == nil:
		cert, err := c.loadCert()
		switch err {
		case nil:
			return cert, nil
		case errExpired:
			return c.generateCert()
		default:
			return nil, err
		}
	case errors.Is(err, os.ErrNotExist):
		return c.generateCert()
	default:
		return nil, fmt.Errorf("could not read cert: %w", err)
	}
}

func (c *Certificate) generateCert() (*x509.Certificate, error) {
	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 127)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		return nil, err
	}

	notAfter := unknownNotAfter
	if c.duration != 0 {
		notAfter = time.Now().Add(c.duration)
	}
	template := c.template()
	template.SerialNumber = serialNumber
	template.NotBefore = time.Now()
	template.NotAfter = notAfter

	parent := template
	skey, err := c.ensureKey()
	if err != nil {
		return nil, fmt.Errorf("when ensuring key: %w", err)
	}
	pkey := skey.Public()
	caskey := skey
	if c.issuer != nil {
		caskey, err = c.issuer.ensureKey()
		if err != nil {
			return nil, fmt.Errorf("when ensuring CA key: %w", err)
		}
		cacert, err := c.issuer.ensureCert()
		if err != nil {
			return nil, fmt.Errorf("when ensuring CA cert: %w", err)
		}
		parent = cacert
	}

	bytes, err := x509.CreateCertificate(rand.Reader, template, parent, pkey, caskey)
	if err != nil {
		return nil, fmt.Errorf("issuing certificate failed: %w", err)
	}

	block := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: bytes})
	path := c.path(fileKindCert)
	os.MkdirAll(filepath.Dir(path), 0700)
	log.Printf("Saving %s cert to %s ...", c.name, path)
	if err := os.WriteFile(path, block, 0600); err != nil {
		return nil, err
	}

	return x509.ParseCertificate(bytes)
}

// errExpired is returned if the cert exists on disk but has (nearly) expired.
var errExpired = errors.New("certificate expired")

func (c *Certificate) loadCert() (*x509.Certificate, error) {
	path := c.path(fileKindCert)
	b, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}

	block, _ := pem.Decode(b)
	if block == nil {
		return nil, fmt.Errorf("no PEM block found")
	}
	if block.Type != "CERTIFICATE" {
		return nil, fmt.Errorf("unexpected PEM block: %q", block.Type)
	}
	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return nil, err
	}
	if time.Now().Add(time.Hour).After(cert.NotAfter) {
		return nil, errExpired
	}
	pkey, ok := cert.PublicKey.(ed25519.PublicKey)
	if !ok {
		return nil, fmt.Errorf("not a ED25519 cert")
	}
	skey, err := c.ensureKey()
	if err != nil {
		return nil, fmt.Errorf("when ensuring key: %w", err)
	}
	if !bytes.Equal(pkey, skey.Public().(ed25519.PublicKey)) {
		return nil, fmt.Errorf("issued for different key")
	}

	template := c.template()
	if err := compareCertData(template, cert); err != nil {
		return nil, err
	}
	return cert, nil
}

// Ensure makes sure the given Certificate (and all of its' issuers) have
// corresponding private keys and X.509 certificates on disk, generating things
// as necessary.
func (c *Certificate) Ensure() error {
	cert, err := c.ensureCert()
	if err != nil {
		return fmt.Errorf("when ensuring cert %s: %w", c.name, err)
	}
	_ = cert

	return nil
}
