from flask import Blueprint, jsonify, request
from server.permissions import editor_or_higher
from server.database import Session
from models.models import Conversion, ConversionStatus, EventMedia, MediaType
from server.task_queue import get_queue
from server.worker import convert_event_media_to_pdf
from datetime import datetime, timezone
import hashlib

conversions_bp = Blueprint("conversions", __name__,
                           url_prefix="/api/conversions")


def sha256_file(abs_path: str) -> str:
    h = hashlib.sha256()
    with open(abs_path, "rb") as f:
        for chunk in iter(lambda: f.read(8192), b""):
            h.update(chunk)
    return h.hexdigest()


@conversions_bp.route("/<int:media_id>/pdf", methods=["POST"])
@editor_or_higher
def ensure_conversion(media_id: int):
    session = Session()
    try:
        media = session.query(EventMedia).get(media_id)
        if not media or not media.file_path:
            return jsonify({"error": "Media not found or no file"}), 404

        # Only enqueue for office presentation formats
        if media.media_type not in {MediaType.ppt, MediaType.pptx, MediaType.odp}:
            return jsonify({"message": "No conversion required for this media_type"}), 200

        # Compute file hash
        import os
        base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        media_root = os.path.join(base_dir, "media")
        abs_source = os.path.join(media_root, media.file_path)
        file_hash = sha256_file(abs_source)

        # Find or create conversion row
        conv = (
            session.query(Conversion)
            .filter_by(
                source_event_media_id=media.id,
                target_format="pdf",
                file_hash=file_hash,
            )
            .one_or_none()
        )
        if not conv:
            conv = Conversion(
                source_event_media_id=media.id,
                target_format="pdf",
                status=ConversionStatus.pending,
                file_hash=file_hash,
            )
            session.add(conv)
            session.commit()

        # Enqueue if not already processing/ready
        if conv.status in {ConversionStatus.pending, ConversionStatus.failed}:
            q = get_queue()
            job = q.enqueue(convert_event_media_to_pdf, conv.id)
            return jsonify({"id": conv.id, "status": conv.status.value, "job_id": job.get_id()}), 202
        else:
            return jsonify({"id": conv.id, "status": conv.status.value, "target_path": conv.target_path}), 200
    finally:
        session.close()


@conversions_bp.route("/<int:media_id>/status", methods=["GET"])
def conversion_status(media_id: int):
    session = Session()
    try:
        conv = (
            session.query(Conversion)
            .filter_by(source_event_media_id=media_id, target_format="pdf")
            .order_by(Conversion.id.desc())
            .first()
        )
        if not conv:
            return jsonify({"status": "missing"}), 404
        return jsonify(
            {
                "id": conv.id,
                "status": conv.status.value,
                "target_path": conv.target_path,
                "started_at": conv.started_at.isoformat() if conv.started_at else None,
                "completed_at": conv.completed_at.isoformat() if conv.completed_at else None,
                "error_message": conv.error_message,
            }
        )
    finally:
        session.close()
