package config

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

	"github.com/pingcap/log"
	"sigs.k8s.io/yaml"
)

type Config struct {
	Debug bool       `json:"debug"`
	Log   log.Config `json:"log"`

	// the domain of the server
	// e.g. ssh.labs.tidb.io
	// it will be used to register the server to lab control plane
	Domain string `json:"domain"`
	// the preferred(low latency) regions of the server
	// control plane will allocate the optimal ssh server to users based on preferred regions
	// e.g. ["oregon", "frankfurt"]
	PreferredRegions []string `json:"preferred_regions"`

	// web console ssh server config
	HttpPort        int    `json:"http_port"`
	JwtPublicKeyPem string `json:"jwt_public_key_pem"`
	JwtPublicKey    ed25519.PublicKey

	// lab api config
	LabBaseURL string `json:"lab_base_url"`
	LabApiKey  string `json:"lab_api_key"`

	SshIdentityFiles map[string]string `json:"ssh_identity_files"`
}

func InitConfig(configPath string) (*Config, error) {
	yamlBytes, err := os.ReadFile(configPath)
	if err != nil {
		return nil, fmt.Errorf("failed to read config file: %v", err)
	}

	var cfg Config
	err = yaml.Unmarshal(yamlBytes, &cfg)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal config file: %v", err)
	}

	cfg.JwtPublicKey, err = cfg.convertJwtPublicKey()
	if err != nil {
		return nil, fmt.Errorf("failed to convert jwt public key: %v", err)
	}

	return &cfg, nil
}

func (c *Config) convertJwtPublicKey() (ed25519.PublicKey, error) {
	block, rest := pem.Decode([]byte(c.JwtPublicKeyPem))
	if block == nil {
		return nil, fmt.Errorf("failed to parse PEM block containing public key")
	}
	if len(rest) > 0 {
		return nil, fmt.Errorf("extra data after PEM block")
	}

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

	edPub, ok := pub.(ed25519.PublicKey)
	if !ok {
		return nil, fmt.Errorf("public key is not Ed25519")
	}
	return edPub, nil
}
