package meshseed

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/ed25519"
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
)

// deriveKey 派生 AES-256-GCM 密钥
// 密钥派生规则：SHA256("meshray-ddns" || NetworkSecret) → 32 字节
func deriveKey(networkSecret string) []byte {
	hash := sha256.Sum256([]byte("meshray-ddns" + networkSecret))
	return hash[:]
}

// Encrypt 加密 MeshSeed
// 流程：签名 → AES-256-GCM 加密 → Base64URL 编码
func Encrypt(seed *MeshSeed, networkSecret string) (string, error) {
	// 1. 签名（如果还没有签名）
	if len(seed.Signature) == 0 {
		// 注意：这里需要 Ed25519 私钥进行签名
		// 由于 MeshSeed 已经包含签名，我们假设签名已经完成
		return "", fmt.Errorf("MeshSeed 未签名")
	}

	// 2. 序列化 MeshSeed
	plaintext, err := json.Marshal(seed)
	if err != nil {
		return "", fmt.Errorf("序列化 MeshSeed 失败：%w", err)
	}

	// 3. 派生加密密钥
	key := deriveKey(networkSecret)

	// 4. 创建 AES cipher
	block, err := aes.NewCipher(key)
	if err != nil {
		return "", fmt.Errorf("创建 AES cipher 失败：%w", err)
	}

	// 5. 创建 GCM
	gcm, err := cipher.NewGCM(block)
	if err != nil {
		return "", fmt.Errorf("创建 GCM 失败：%w", err)
	}

	// 6. 生成随机 Nonce
	nonce := make([]byte, gcm.NonceSize())
	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
		return "", fmt.Errorf("生成 Nonce 失败：%w", err)
	}

	// 7. 加密
	ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)

	// 8. Base64URL 编码
	encoded := base64.URLEncoding.EncodeToString(ciphertext)

	return encoded, nil
}

// Decrypt 解密 MeshSeed
// 流程：Base64URL 解码 → AES-256-GCM 解密 → Ed25519 验签
func Decrypt(encrypted string, networkSecret string) (*MeshSeed, error) {
	// 1. Base64URL 解码
	ciphertext, err := base64.URLEncoding.DecodeString(encrypted)
	if err != nil {
		return nil, fmt.Errorf("Base64URL 解码失败：%w", err)
	}

	// 2. 派生解密密钥
	key := deriveKey(networkSecret)

	// 3. 创建 AES cipher
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, fmt.Errorf("创建 AES cipher 失败：%w", err)
	}

	// 4. 创建 GCM
	gcm, err := cipher.NewGCM(block)
	if err != nil {
		return nil, fmt.Errorf("创建 GCM 失败：%w", err)
	}

	// 5. 检查密文长度
	nonceSize := gcm.NonceSize()
	if len(ciphertext) < nonceSize {
		return nil, fmt.Errorf("密文长度不足")
	}

	// 6. 分离 Nonce 和密文
	nonce, ciphertextBytes := ciphertext[:nonceSize], ciphertext[nonceSize:]

	// 7. 解密
	plaintext, err := gcm.Open(nil, nonce, ciphertextBytes, nil)
	if err != nil {
		return nil, fmt.Errorf("解密失败：%w", err)
	}

	// 8. 反序列化 MeshSeed
	var seed MeshSeed
	if err := json.Unmarshal(plaintext, &seed); err != nil {
		return nil, fmt.Errorf("反序列化 MeshSeed 失败：%w", err)
	}

	return &seed, nil
}

// Sign 签名 MeshSeed
// 使用 Ed25519 私钥对 MeshSeed 进行签名
func Sign(seed *MeshSeed, privateKey ed25519.PrivateKey) error {
	// 1. 临时清除签名字段
	originalSignature := seed.Signature
	seed.Signature = nil

	// 2. 序列化 MeshSeed（不含签名）
	data, err := json.Marshal(seed)
	if err != nil {
		seed.Signature = originalSignature
		return fmt.Errorf("序列化 MeshSeed 失败：%w", err)
	}

	// 3. Ed25519 签名
	signature := ed25519.Sign(privateKey, data)

	// 4. 设置签名
	seed.Signature = signature

	return nil
}

// Verify 验证 MeshSeed 签名
// 使用 Ed25519 公钥验证 MeshSeed 签名
// 可选参数 publicKey：如果为 nil，则从 seed.IssuerNodeID 解析公钥
func Verify(seed *MeshSeed, publicKey ed25519.PublicKey) error {
	// 1. 检查签名是否存在
	if len(seed.Signature) == 0 {
		return fmt.Errorf("MeshSeed 无签名")
	}

	// 2. 如果未提供公钥，从 IssuerNodeID 解析
	if publicKey == nil {
		if seed.IssuerNodeID == "" {
			return fmt.Errorf("无法验证签名：缺少公钥（IssuerNodeID 为空）")
		}
		// IssuerNodeID 是 hex 编码的 Ed25519 公钥（32 字节）
		pubKeyBytes, err := decodeIssuerNodeID(seed.IssuerNodeID)
		if err != nil {
			return fmt.Errorf("解析 IssuerNodeID 失败：%w", err)
		}
		if len(pubKeyBytes) != ed25519.PublicKeySize {
			return fmt.Errorf("无效的公钥长度：期望 %d 字节，实际 %d 字节",
				ed25519.PublicKeySize, len(pubKeyBytes))
		}
		publicKey = ed25519.PublicKey(pubKeyBytes)
	}

	// 3. 临时保存签名
	signature := seed.Signature

	// 4. 临时清除签名字段
	seed.Signature = nil

	// 5. 序列化 MeshSeed（不含签名）
	data, err := json.Marshal(seed)
	if err != nil {
		seed.Signature = signature
		return fmt.Errorf("序列化 MeshSeed 失败：%w", err)
	}

	// 6. 恢复签名
	seed.Signature = signature

	// 7. Ed25519 验签
	if !ed25519.Verify(publicKey, data, signature) {
		return fmt.Errorf("签名验证失败：签名无效或数据被篡改")
	}

	return nil
}

// decodeIssuerNodeID 解码 IssuerNodeID 为公钥字节
// 支持两种格式：hex 编码（64 字符）或 Base64 编码
func decodeIssuerNodeID(id string) ([]byte, error) {
	// 尝试 hex 解码（64 字符 = 32 字节）
	if len(id) == 64 {
		return hexDecodeString(id)
	}

	// 尝试 Base64 解码
	return base64.StdEncoding.DecodeString(id)
}

// hexDecodeString 解码 hex 字符串（辅助函数）
func hexDecodeString(s string) ([]byte, error) {
	// 手动实现 hex 解码以避免导入 encoding/hex
	result := make([]byte, len(s)/2)
	for i := 0; i < len(s); i += 2 {
		b1, ok := hexCharToByte(s[i])
		if !ok {
			return nil, fmt.Errorf("无效的 hex 字符：%c", s[i])
		}
		b2, ok := hexCharToByte(s[i+1])
		if !ok {
			return nil, fmt.Errorf("无效的 hex 字符：%c", s[i+1])
		}
		result[i/2] = b1<<4 | b2
	}
	return result, nil
}

// hexCharToByte 单个 hex 字符转字节
func hexCharToByte(c byte) (byte, bool) {
	switch {
	case '0' <= c && c <= '9':
		return c - '0', true
	case 'a' <= c && c <= 'f':
		return c - 'a' + 10, true
	case 'A' <= c && c <= 'F':
		return c - 'A' + 10, true
	default:
		return 0, false
	}
}

// GenerateKeyPair 生成 Ed25519 密钥对
func GenerateKeyPair() (ed25519.PublicKey, ed25519.PrivateKey, error) {
	publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)
	if err != nil {
		return nil, nil, fmt.Errorf("生成密钥对失败：%w", err)
	}
	return publicKey, privateKey, nil
}
