"""
media.py — Media Ingestion Layer

Media ingestion layer.
Responsibilities: hash computation + Claude API semantic analysis.
Principle: descriptions persist forever, files can be lost; hash is the identity, path is just a hint.
"""

import base64
import hashlib
from pathlib import Path


def compute_hash(file_path: str) -> str:
    """SHA256, the file's identity — path-independent, portable."""
    h = hashlib.sha256()
    with open(file_path, "rb") as f:
        for chunk in iter(lambda: f.read(65536), b""):
            h.update(chunk)
    return h.hexdigest()


def read_binary(file_path: str) -> bytes:
    with open(file_path, "rb") as f:
        return f.read()


# Extension → MIME
_IMAGE_MIME = {
    ".jpg": "image/jpeg", ".jpeg": "image/jpeg",
    ".png": "image/png",  ".gif": "image/gif",
    ".webp": "image/webp", ".bmp": "image/bmp",
}
_AUDIO_MIME = {
    ".mp3": "audio/mpeg", ".wav": "audio/wav",
    ".m4a": "audio/mp4",  ".ogg": "audio/ogg",
    ".flac": "audio/flac", ".aac": "audio/aac",
}
_VIDEO_EXT = {".mp4", ".mov", ".avi", ".mkv", ".webm"}


def describe_media(file_path: str, artifact_type: str, extra_context: str = "") -> str:
    """
    Generate semantic description of media using Claude API.
    Image → visual analysis; Audio → content analysis; Video → requires manual description (returns prompt).
    Description is the soul's fallback — even if the file is lost, the text persists forever.
    """
    path = Path(file_path)
    suffix = path.suffix.lower()

    if artifact_type == "image" or suffix in _IMAGE_MIME:
        return _describe_image(path, suffix, extra_context)
    elif artifact_type == "audio" or suffix in _AUDIO_MIME:
        return _describe_audio(path, suffix, extra_context)
    elif artifact_type == "video" or suffix in _VIDEO_EXT:
        size_mb = path.stat().st_size / (1024 * 1024)
        note = f"Video file: {path.name}, size: {size_mb:.1f}MB, format: {suffix[1:].upper()}."
        if extra_context:
            return note + "\n" + extra_context
        return note + " (Please describe video content via the extra_context parameter.)"
    else:
        size_kb = path.stat().st_size // 1024
        base = f"File: {path.name}, type: {artifact_type}, size: {size_kb}KB."
        return base + (extra_context or "")


def _describe_image(path: Path, suffix: str, extra_context: str) -> str:
    import anthropic
    media_type = _IMAGE_MIME.get(suffix, "image/jpeg")
    data = read_binary(str(path))
    b64 = base64.standard_b64encode(data).decode()

    prompt = (
        "Please describe in detail the person in this image: facial features, expression, "
        "clothing, posture, background environment, and overall atmosphere. "
        "This is a core visual record for a digital soul archive. "
        "The description must be detailed enough that any future AI can reconstruct "
        "a complete impression of this person's appearance from text alone."
    )
    if extra_context:
        prompt += f"\nAdditional context: {extra_context}"

    try:
        client = anthropic.Anthropic()
        msg = client.messages.create(
            model="claude-opus-4-6",
            max_tokens=1024,
            messages=[{
                "role": "user",
                "content": [
                    {"type": "image",
                     "source": {"type": "base64", "media_type": media_type, "data": b64}},
                    {"type": "text", "text": prompt},
                ],
            }],
        )
        return msg.content[0].text
    except Exception as e:
        size_kb = path.stat().st_size // 1024
        fallback = f"Image file: {path.name}, size: {size_kb}KB. (Auto-analysis failed: {str(e)[:120]})"
        if extra_context:
            fallback += f"\nManual description: {extra_context}"
        return fallback


def _describe_audio(path: Path, suffix: str, extra_context: str) -> str:
    import anthropic
    media_type = _AUDIO_MIME.get(suffix, "audio/mpeg")
    data = read_binary(str(path))
    b64 = base64.standard_b64encode(data).decode()

    prompt = (
        "Please describe this audio: speech content (as verbatim as possible), "
        "voice characteristics (pitch/speed/emotion/texture), and background environmental sounds. "
        "This is a voice record for a digital soul — preserve as much detail as possible."
    )
    if extra_context:
        prompt += f"\nAdditional context: {extra_context}"

    try:
        client = anthropic.Anthropic()
        msg = client.messages.create(
            model="claude-opus-4-6",
            max_tokens=1024,
            messages=[{
                "role": "user",
                "content": [
                    {"type": "document",
                     "source": {"type": "base64", "media_type": media_type, "data": b64}},
                    {"type": "text", "text": prompt},
                ],
            }],
        )
        return msg.content[0].text
    except Exception as e:
        size_kb = path.stat().st_size // 1024
        fallback = f"Audio file: {path.name}, size: {size_kb}KB. (Auto-analysis failed: {str(e)[:120]})"
        if extra_context:
            fallback += f"\nManual description: {extra_context}"
        return fallback
