import os
import traceback
from datetime import datetime, timezone

import requests
from sqlalchemy.orm import Session as SASession

from server.database import Session
from models.models import Conversion, ConversionStatus, EventMedia, MediaType

GOTENBERG_URL = os.getenv("GOTENBERG_URL", "http://gotenberg:3000")


def _now():
    return datetime.now(timezone.utc)


def convert_event_media_to_pdf(conversion_id: int):
    """
    Job entry point: convert a single EventMedia to PDF using Gotenberg.

    Steps:
      - Load conversion + source media
      - Set status=processing, started_at
      - POST to Gotenberg /forms/libreoffice/convert with the source file bytes
      - Save response bytes to target_path
      - Set status=ready, completed_at, target_path
      - On error: set status=failed, error_message
    """
    session: SASession = Session()
    try:
        conv: Conversion = session.query(Conversion).get(conversion_id)
        if not conv:
            return

        media: EventMedia = session.query(
            EventMedia).get(conv.source_event_media_id)
        if not media or not media.file_path:
            conv.status = ConversionStatus.failed
            conv.error_message = "Source media or file_path missing"
            conv.completed_at = _now()
            session.commit()
            return

        conv.status = ConversionStatus.processing
        conv.started_at = _now()
        session.commit()

        # Get the server directory (where this worker.py file is located)
        server_dir = os.path.dirname(os.path.abspath(__file__))
        media_root = os.path.join(server_dir, "media")
        abs_source = os.path.join(media_root, media.file_path)
        # Output target under media/converted
        converted_dir = os.path.join(media_root, "converted")
        os.makedirs(converted_dir, exist_ok=True)
        filename_wo_ext = os.path.splitext(
            os.path.basename(media.file_path))[0]
        pdf_name = f"{filename_wo_ext}.pdf"
        abs_target = os.path.join(converted_dir, pdf_name)

        # Send to Gotenberg
        with open(abs_source, "rb") as f:
            files = {"files": (os.path.basename(abs_source), f)}
            resp = requests.post(
                f"{GOTENBERG_URL}/forms/libreoffice/convert",
                files=files,
                timeout=600,
            )
            resp.raise_for_status()

        with open(abs_target, "wb") as out:
            out.write(resp.content)

        conv.status = ConversionStatus.ready
        # Store relative path under media/
        conv.target_path = os.path.relpath(abs_target, media_root)
        conv.completed_at = _now()
        session.commit()
    except requests.exceptions.Timeout:
        conv = session.query(Conversion).get(conversion_id)
        if conv:
            conv.status = ConversionStatus.failed
            conv.error_message = "Conversion timeout"
            conv.completed_at = _now()
            session.commit()
    except Exception as e:
        conv = session.query(Conversion).get(conversion_id)
        if conv:
            conv.status = ConversionStatus.failed
            conv.error_message = f"{e}\n{traceback.format_exc()}"
            conv.completed_at = _now()
            session.commit()
    finally:
        session.close()
