"""Digital signature generation and verification."""

import hashlib
import json
from datetime import datetime
from pathlib import Path
from typing import Any, Dict

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa


class SignatureEngine:
    """Handles C2PA-style digital signatures for media files."""

    def __init__(self, key_path: Path = None):
        self.key_path = key_path or Path.home() / ".synth-comply" / "signing_key.pem"
        self.public_key_path = self.key_path.with_suffix(".pub")
        self._ensure_keys()

    def _ensure_keys(self):
        """Generate RSA keypair if not exists."""
        if not self.key_path.exists():
            self.key_path.parent.mkdir(parents=True, exist_ok=True)

            # Generate private key
            private_key = rsa.generate_private_key(
                public_exponent=65537, key_size=2048, backend=default_backend()
            )

            # Save private key
            pem = private_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.PKCS8,
                encryption_algorithm=serialization.NoEncryption(),
            )
            self.key_path.write_bytes(pem)
            self.key_path.chmod(0o600)

            # Save public key
            public_key = private_key.public_key()
            public_pem = public_key.public_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PublicFormat.SubjectPublicKeyInfo,
            )
            self.public_key_path.write_bytes(public_pem)

    def sign_file(self, file_path: Path) -> Dict[str, Any]:
        """Generate digital signature for a file."""

        # Compute file hash
        file_hash = self._compute_hash(file_path)

        # Load private key
        private_key = serialization.load_pem_private_key(
            self.key_path.read_bytes(), password=None, backend=default_backend()
        )

        # Sign the hash
        signature = private_key.sign(
            file_hash.encode(), padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH
            ), hashes.SHA256()
        )

        return {
            "signature": signature.hex(),
            "algorithm": "RSA-SHA256-PSS",
            "file_hash": file_hash,
            "timestamp": datetime.utcnow().isoformat(),
            "metadata": {
                "file_name": file_path.name,
                "file_size": file_path.stat().st_size,
            },
        }

    def verify_file(self, file_path: Path, signature_hex: str) -> bool:
        """Verify file signature."""

        try:
            # Compute current file hash
            current_hash = self._compute_hash(file_path)

            # Load public key
            public_key = serialization.load_pem_public_key(
                self.public_key_path.read_bytes(), backend=default_backend()
            )

            # Verify signature
            signature_bytes = bytes.fromhex(signature_hex)
            public_key.verify(
                signature_bytes,
                current_hash.encode(),
                padding.PSS(
                    mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH
                ),
                hashes.SHA256(),
            )
            return True

        except Exception:
            return False

    def _compute_hash(self, file_path: Path) -> str:
        """Compute SHA-256 hash of file."""
        sha256 = hashlib.sha256()
        with open(file_path, "rb") as f:
            for chunk in iter(lambda: f.read(8192), b""):
                sha256.update(chunk)
        return sha256.hexdigest()
