package licensecheck

import (
	"crypto/ecdsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/asn1"
	"encoding/base64"
	"encoding/json"
	"encoding/pem"
	"errors"
	"math/big"
	"os"
	"strings"
	"time"

	"intent-system/internal/hostid" // 你的 GetRootDiskSerial 包
)

/* ---------- ① 常量：内置公钥 ---------- */
const publicKeyPEM = `-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKQtVKlXjOro4qPoavqOU8m5qda0k
olAhHgTayzNuR+nOP1AnjQm10ehhV7Aafo8fUnjxs/rAM+MRdmzcEXrWnw==
-----END PUBLIC KEY-----`

/* ---------- ② 与服务端保持一致的结构 ---------- */
type licenseRequest struct {
	MachineID string   `json:"machine_id"`
	Expiry    string   `json:"expiry"`
	Features  []string `json:"features"`
}

/* ---------- ③ 入口：Validate(path) ---------- */
func Validate(licPath string) error {
	raw, err := os.ReadFile(licPath)
	if err != nil {
		return err
	}
	parts := strings.Split(strings.TrimSpace(string(raw)), ".")
	if len(parts) != 2 {
		return errors.New("invalid license format")
	}
	payloadB64, sigB64 := parts[0], parts[1]

	payload, err := base64.StdEncoding.DecodeString(payloadB64)
	if err != nil {
		return errors.New("payload base64 decode failed")
	}

	// 1. 验签
	pubKey, err := parsePublicKey(publicKeyPEM)
	if err != nil {
		return err
	}
	if !verifySignature(pubKey, payload, sigB64) {
		return errors.New("signature mismatch")
	}

	// 2. 解析字段
	var req licenseRequest
	if err := json.Unmarshal(payload, &req); err != nil {
		return err
	}

	// 3. 校验机身号
	sn, err := hostid.GetRootDiskSerial()
	if err != nil {
		return err
	}
	if req.MachineID != sn {
		return errors.New("machine ID mismatch")
	}

	// 4. 校验过期
	expiry, err := time.Parse("2006-01-02", req.Expiry)
	if err != nil || time.Now().After(expiry) {
		return errors.New("license expired")
	}

	return nil // 👍 通过
}

/* ---------- ④ 辅助函数 ---------- */
func parsePublicKey(pemStr string) (*ecdsa.PublicKey, error) {
	block, _ := pem.Decode([]byte(pemStr))
	if block == nil || block.Type != "PUBLIC KEY" {
		return nil, errors.New("invalid PEM")
	}
	pubAny, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	return pubAny.(*ecdsa.PublicKey), nil
}

type ecdsaSig struct{ R, S *big.Int }

func verifySignature(pub *ecdsa.PublicKey, msg []byte, sigB64 string) bool {
	sigBytes, err := base64.StdEncoding.DecodeString(sigB64)
	if err != nil {
		return false
	}
	var sig ecdsaSig
	if _, err = asn1.Unmarshal(sigBytes, &sig); err != nil {
		return false
	}
	hash := sha256.Sum256(msg)
	return ecdsa.Verify(pub, hash[:], sig.R, sig.S)
}
