from __future__ import annotations

import json
from typing import Any

from cryptography.fernet import Fernet, InvalidToken


class SecretVault:
    def __init__(self, key: str) -> None:
        try:
            self._fernet = Fernet(key.encode("ascii"))
        except (ValueError, TypeError) as exc:
            raise ValueError("DATAHUB_ENCRYPTION_KEY 格式无效。") from exc

    @staticmethod
    def generate_key() -> str:
        return Fernet.generate_key().decode("ascii")

    def encrypt_json(self, payload: dict[str, Any]) -> str:
        raw = json.dumps(payload, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
        return self._fernet.encrypt(raw).decode("ascii")

    def decrypt_json(self, token: str) -> dict[str, Any]:
        if not token:
            return {}
        try:
            payload = json.loads(self._fernet.decrypt(token.encode("ascii")).decode("utf-8"))
        except (InvalidToken, UnicodeDecodeError, json.JSONDecodeError) as exc:
            raise ValueError("凭据无法解密，请检查 DATAHUB_ENCRYPTION_KEY。") from exc
        if not isinstance(payload, dict):
            raise ValueError("凭据格式无效。")
        return payload


def mask_secret(value: str, last_n: int = 4) -> str:
    text = str(value or "")
    if not text:
        return ""
    if len(text) <= last_n:
        return "*" * len(text)
    return ("*" * max(4, len(text) - last_n)) + text[-last_n:]
