"""Local Ed25519 signing and watermark embedding engine."""
import hashlib
import io
from datetime import datetime, timezone

import numpy as np
from PIL import Image
from nacl.signing import SigningKey as NaClSigningKey, VerifyKey
from nacl.encoding import HexEncoder
from cryptography.fernet import Fernet
from imwatermark import WatermarkEncoder, WatermarkDecoder
import imagehash


WATERMARK_METHOD = "dwtDct"


def compute_sha256(data: bytes) -> str:
    return hashlib.sha256(data).hexdigest()


def compute_perceptual_hash(image_bytes: bytes) -> str:
    img = Image.open(io.BytesIO(image_bytes))
    return str(imagehash.phash(img, hash_size=8))


def decrypt_private_key(encrypted: str, fernet_key: str) -> str:
    f = Fernet(fernet_key.encode() if isinstance(fernet_key, str) else fernet_key)
    return f.decrypt(encrypted.encode()).decode()


def sign_message(private_key_hex: str, message: bytes) -> bytes:
    sk = NaClSigningKey(private_key_hex.encode(), encoder=HexEncoder)
    signed = sk.sign(message)
    return signed.signature


def embed_watermark(image_bytes: bytes, payload: bytes) -> bytes:
    payload_padded = payload[:32].ljust(32, b"\x00")
    img = Image.open(io.BytesIO(image_bytes)).convert("RGB")
    img_array = np.array(img)
    encoder = WatermarkEncoder()
    encoder.set_watermark("bytes", payload_padded)
    watermarked = encoder.encode(img_array, WATERMARK_METHOD)
    out_buf = io.BytesIO()
    Image.fromarray(watermarked).save(out_buf, format="PNG")
    return out_buf.getvalue()


def sign_image_locally(
    image_bytes: bytes,
    private_key_hex: str,
    user_id: str,
) -> dict:
    """Sign an image entirely locally.

    Returns a dict with all metadata needed to register with the backend.
    """
    sha256 = compute_sha256(image_bytes)
    phash = compute_perceptual_hash(image_bytes)
    timestamp = datetime.now(timezone.utc)

    fingerprint_data = f"{sha256}|{phash}|{int(timestamp.timestamp())}|{user_id}".encode()
    signature = sign_message(private_key_hex, fingerprint_data)
    signature_hex = signature.hex()

    watermark_payload = hashlib.sha256(signature).digest()[:16]
    watermark_payload_hex = watermark_payload.hex()

    watermarked_bytes = embed_watermark(image_bytes, watermark_payload)

    return {
        "sha256_hash": sha256,
        "perceptual_hash": phash,
        "signature_hex": signature_hex,
        "watermark_payload_hex": watermark_payload_hex,
        "watermarked_bytes": watermarked_bytes,
        "timestamp": timestamp,
        "file_size": len(image_bytes),
    }
