// Package proxy 反向代理包，为 Lolly HTTP 服务器提供反向代理功能。
//
// 该文件提供上游 SSL/TLS 配置支持，包括自定义 CA 证书、
// 客户端证书（mTLS）、SNI 和 TLS 版本控制。
//
// 主要功能：
//   - 自定义 CA 证书验证：支持指定受信任的 CA 证书文件
//   - 客户端证书认证（mTLS）：支持双向 TLS 认证
//   - SNI 支持：自动从目标 URL 提取或使用配置的主机名
//   - TLS 版本控制：支持 TLSv1.0 到 TLSv1.3 的最小/最大版本限制
//   - 跳过证书验证：仅测试环境使用
//
// 主要用途：
//
//	用于代理与上游服务器之间的 TLS 连接配置，支持自签名证书、
//	内部 CA 签发证书以及双向认证场景。
//
// 注意事项：
//   - InsecureSkipVerify 仅建议在测试环境使用
//   - 证书文件路径为绝对路径或相对于工作目录
//
// 作者：xfy
package proxy

import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"os"
	"strings"

	"rua.plus/lolly/internal/config"
	"rua.plus/lolly/internal/logging"
	"rua.plus/lolly/internal/sslutil"
)

// CreateTLSConfig 从 ProxySSLConfig 创建 tls.Config。
//
// 参数：
//   - cfg: 上游 SSL 配置
//   - defaultServerName: 默认 SNI 名称（从目标 URL 提取）
//
// 返回值：
//   - *tls.Config: TLS 配置对象
//   - error: 配置错误（证书加载失败等）
//
// 注意事项：
//   - cfg 为 nil 或 Enabled=false 时返回 nil
//   - TrustedCA 加载失败时返回错误
//   - ClientCert/ClientKey 加载失败时返回错误
func CreateTLSConfig(cfg *config.ProxySSLConfig, defaultServerName string) (*tls.Config, error) {
	if cfg == nil || !cfg.Enabled {
		return nil, nil
	}

	tlsCfg := &tls.Config{}

	// SNI 配置
	if cfg.ServerName != "" {
		tlsCfg.ServerName = cfg.ServerName
	} else if defaultServerName != "" {
		tlsCfg.ServerName = defaultServerName
	}

	// 跳过证书验证（仅测试环境）
	if cfg.InsecureSkipVerify {
		tlsCfg.InsecureSkipVerify = true
	}

	// CA 证书验证
	if cfg.TrustedCA != "" {
		caData, err := os.ReadFile(cfg.TrustedCA)
		if err != nil {
			return nil, errors.New("failed to read CA certificate: " + err.Error())
		}

		caPool := x509.NewCertPool()
		if !caPool.AppendCertsFromPEM(caData) {
			return nil, errors.New("failed to parse CA certificate")
		}
		tlsCfg.RootCAs = caPool
	}

	// 客户端证书（mTLS）
	if cfg.ClientCert != "" && cfg.ClientKey != "" {
		cert, err := tls.LoadX509KeyPair(cfg.ClientCert, cfg.ClientKey)
		if err != nil {
			return nil, errors.New("failed to load client certificate: " + err.Error())
		}
		tlsCfg.Certificates = []tls.Certificate{cert}
	}

	// TLS 版本配置：默认 MinVersion = TLS 1.2
	tlsCfg.MinVersion = tls.VersionTLS12

	if cfg.MinVersion != "" {
		version, ok := sslutil.TLSVersionMap[strings.ToUpper(cfg.MinVersion)]
		if !ok {
			return nil, errors.New("invalid TLS min version: " + cfg.MinVersion)
		}
		tlsCfg.MinVersion = version
	}

	// 警告：TLS 1.0/1.1 已不安全，不应在生产环境使用
	if tlsCfg.MinVersion < tls.VersionTLS12 {
		logging.Warn().Msgf("上游 TLS MinVersion 设置为 %s（低于 TLS 1.2），存在安全风险", cfg.MinVersion)
	}

	if cfg.MaxVersion != "" {
		version, ok := sslutil.TLSVersionMap[strings.ToUpper(cfg.MaxVersion)]
		if !ok {
			return nil, errors.New("invalid TLS max version: " + cfg.MaxVersion)
		}
		tlsCfg.MaxVersion = version
	}

	return tlsCfg, nil
}
