import hashlib
import logging
import uuid
from pathlib import Path

logger = logging.getLogger(__name__)

_PULI_DIR = Path.home() / ".puli"
_MACHINE_ID_FILE = _PULI_DIR / "machine_id"
_TOKEN_FILE = _PULI_DIR / "token"
_API_KEY_HASH_FILE = _PULI_DIR / "api_key_hash"


def _ensure_dir() -> None:
    _PULI_DIR.mkdir(mode=0o700, exist_ok=True)


def _hash_api_key(api_key: str) -> str:
    """Create a hash of the API key for validation."""
    return hashlib.sha256(api_key.encode()).hexdigest()


def get_machine_id() -> str:
    _ensure_dir()
    if _MACHINE_ID_FILE.exists():
        return _MACHINE_ID_FILE.read_text().strip()
    machine_id = str(uuid.uuid4())
    _MACHINE_ID_FILE.write_text(machine_id)
    return machine_id


def read_token(api_key: str) -> str | None:
    """Read token only if it matches the current API key.
    
    Args:
        api_key: Current API key to validate against cached token.
        
    Returns:
        Cached token if API key matches, None otherwise.
    """
    if not _TOKEN_FILE.exists():
        return None
    
    # Check if API key hash matches
    if _API_KEY_HASH_FILE.exists():
        cached_hash = _API_KEY_HASH_FILE.read_text().strip()
        current_hash = _hash_api_key(api_key)
        
        if cached_hash != current_hash:
            # API key changed, invalidate cached token
            logger.info("API key changed, invalidating cached token and re-registering")
            clear_token()
            return None
    
    token = _TOKEN_FILE.read_text().strip()
    return token or None


def write_token(token: str, api_key: str) -> None:
    """Write token and API key hash to disk.
    
    Args:
        token: JWT token from authentication.
        api_key: API key used for this token.
    """
    _ensure_dir()
    _TOKEN_FILE.write_text(token)
    _API_KEY_HASH_FILE.write_text(_hash_api_key(api_key))


def clear_token() -> None:
    """Remove cached token and API key hash."""
    if _TOKEN_FILE.exists():
        _TOKEN_FILE.unlink()
    if _API_KEY_HASH_FILE.exists():
        _API_KEY_HASH_FILE.unlink()
