from __future__ import annotations

import logging
from datetime import datetime, timezone

from django.core.files.base import ContentFile

from apps.books.models import EBook
from apps.books.services.openlibrary import (
    HIGH_CONFIDENCE,
    download_cover,
    fetch_metadata,
)

logger = logging.getLogger(__name__)


def enrich_ebook_metadata(ebook: EBook) -> EBook:
    """Fetch Open Library metadata and update the ebook. Never raises to callers."""
    user_title = ebook.title
    user_author = ebook.author or ""

    try:
        result = fetch_metadata(user_title, user_author)
    except Exception:
        logger.exception("Open Library metadata fetch failed for ebook %s", ebook.pk)
        return ebook

    if result is None:
        return ebook

    now = datetime.now(timezone.utc).isoformat()
    metadata = {
        "source": "openlibrary",
        "matched_at": now,
        "match_language": result.match_language,
        "match_score": result.match_score,
        "match_status": result.match_status,
        "user_input": {"title": user_title, "author": user_author},
        "openlibrary": result.openlibrary,
    }
    ebook.metadata_json = metadata

    update_fields = ["metadata_json", "updated_at"]

    if result.match_status == "not_found":
        ebook.save(update_fields=update_fields)
        return ebook

    ol = result.openlibrary
    cover_id = ol.get("cover_id")

    cover_missing = (
        not ebook.cover_image
        or not ebook.cover_image.name
        or not ebook.cover_image.storage.exists(ebook.cover_image.name)
    )
    if cover_id and cover_missing:
        if ebook.cover_image:
            ebook.cover_image.delete(save=False)
        cover_bytes = download_cover(int(cover_id))
        if cover_bytes:
            filename = f"ol_cover_{ebook.pk}_{cover_id}.jpg"
            ebook.cover_image.save(filename, ContentFile(cover_bytes), save=False)
            update_fields.append("cover_image")

    if result.match_score >= HIGH_CONFIDENCE:
        ol_title = ol.get("title")
        ol_authors = ol.get("authors") or []
        if ol_title:
            ebook.title = ol_title[:512]
            update_fields.append("title")
        if ol_authors:
            ebook.author = ol_authors[0][:256]
            update_fields.append("author")

    ebook.save(update_fields=list(dict.fromkeys(update_fields)))
    return ebook
