package config

import (
	"fmt"
	"strings"
)

// TLSConf describes one authenticated TLS 1.3 endpoint. Certificate paths are
// deployment inputs; they never contain certificate or private-key material.
// PeerRole and PeerName bind the remote certificate to an IOP workload
// identity in addition to the normal CA and DNS-name verification.
type TLSConf struct {
	Enabled    bool   `mapstructure:"enabled"     yaml:"enabled"`
	Cert       string `mapstructure:"cert"        yaml:"cert"`
	Key        string `mapstructure:"key"         yaml:"key"`
	CA         string `mapstructure:"ca"          yaml:"ca"`
	ServerName string `mapstructure:"server_name" yaml:"server_name,omitempty"`
	PeerRole   string `mapstructure:"peer_role"   yaml:"peer_role,omitempty"`
	PeerName   string `mapstructure:"peer_name"   yaml:"peer_name,omitempty"`
}

// ValidateHTTPServer checks a server-authenticated HTTPS endpoint. Principal
// authentication remains at the HTTP layer, so a client certificate is not
// required on this public boundary.
func (c TLSConf) ValidateHTTPServer() error {
	if !c.Enabled {
		return nil
	}
	if strings.TrimSpace(c.Cert) == "" || strings.TrimSpace(c.Key) == "" {
		return fmt.Errorf("tls cert and key are required when enabled")
	}
	return nil
}

// ValidateServer checks the fields required by an mTLS server. expectedRole is
// the role the caller requires from connecting clients.
func (c TLSConf) ValidateServer(expectedRole string) error {
	if !c.Enabled {
		return nil
	}
	if strings.TrimSpace(c.Cert) == "" || strings.TrimSpace(c.Key) == "" || strings.TrimSpace(c.CA) == "" {
		return fmt.Errorf("tls cert, key, and ca are required when enabled")
	}
	role := strings.TrimSpace(c.PeerRole)
	if role == "" {
		role = strings.TrimSpace(expectedRole)
	}
	if role == "" {
		return fmt.Errorf("tls peer_role is required when enabled")
	}
	return nil
}

// ValidateClient checks the fields required by an mTLS client. expectedRole is
// the role the caller requires from the server certificate.
func (c TLSConf) ValidateClient(expectedRole string) error {
	if err := c.ValidateServer(expectedRole); err != nil {
		return err
	}
	if c.Enabled && strings.TrimSpace(c.ServerName) == "" {
		return fmt.Errorf("tls server_name is required for a client when enabled")
	}
	return nil
}

// EffectivePeerRole returns the configured peer role or the boundary default.
func (c TLSConf) EffectivePeerRole(defaultRole string) string {
	if role := strings.TrimSpace(c.PeerRole); role != "" {
		return role
	}
	return strings.TrimSpace(defaultRole)
}
