import hashlib
from pathlib import Path

from fastapi import APIRouter, Form, HTTPException, UploadFile

from app.config import settings
from app.services.d2l import D2LService
from app.services.media import MediaService
from app.services.paperless import PaperlessService
from app.services.repository import get_repository
from app.services.store import JsonStore
from app.services.webhooks import WebhookService


router = APIRouter(prefix="/api/recordings", tags=["recordings"])
store = JsonStore()
repo = get_repository()
d2l = D2LService()
paperless = PaperlessService()
media = MediaService()
webhooks = WebhookService()


@router.get("")
async def list_recordings():
    return {"items": repo.list_recordings(), "backend": repo.backend}


@router.post("/intake")
async def intake_recording(
    file: UploadFile,
    class_id: str = Form(...),
    class_name: str = Form(...),
    session_date: str = Form(...),
    assignment_id: str | None = Form(None),
    notes: str = Form(""),
):
    course = next((item for item in d2l.get_courses() if str(item.get("d2l_course_id") or item.get("id")) == str(class_id)), None)
    if not course:
        raise HTTPException(status_code=404, detail="Class not found in cached D2L data.")

    upload_root = Path(settings.upload_tmp_dir)
    upload_root.mkdir(parents=True, exist_ok=True)
    recording_id = store.new_id("recording")
    safe_name = Path(file.filename or "recording.wav").name
    stored_path = upload_root / f"{recording_id}-{safe_name}"
    payload = await file.read()
    stored_path.write_bytes(payload)
    checksum = hashlib.sha256(payload).hexdigest()
    mp3_path = media.planned_mp3_path(str(stored_path))

    record = {
        "id": recording_id,
        "class_id": str(course.get("d2l_course_id") or class_id),
        "class_name": class_name,
        "assignment_id": assignment_id,
        "session_date": session_date,
        "notes": notes,
        "original_filename": safe_name,
        "stored_path": str(stored_path),
        "mp3_path": mp3_path,
        "conversion_command": media.conversion_command(str(stored_path), mp3_path),
        "delete_wav_after_success": True,
        "mime_type": file.content_type or "audio/wav",
        "file_size_bytes": len(payload),
        "checksum_sha256": checksum,
        "status": "uploaded-local",
        "conversion_status": "queued",
        "transcription_status": "queued",
        "summary_status": "queued",
        "received_at": store.now(),
    }
    record["paperless_handoff"] = paperless.recording_intake_payload(record)
    created = repo.create_recording(record)
    return {"status": "ok", "recording": created, "backend": repo.backend}


@router.post("/{recording_id}/reprocess")
async def reprocess_recording(recording_id: str):
    recordings = repo.list_recordings()
    current = next((item for item in recordings if str(item.get("id")) == str(recording_id)), None)
    if not current:
        raise HTTPException(status_code=404, detail="Recording not found.")
    handoff = paperless.recording_intake_payload(current)
    file_path = current.get("mp3_path") or current.get("stored_path") or current.get("local_file")
    if not file_path or not Path(file_path).exists():
        raise HTTPException(status_code=400, detail="Local recording file is missing.")
    fields = {
        "class_name": handoff["class_name"],
        "lecture_title": handoff["lecture_title"],
        "notes": handoff.get("notes", ""),
        "source": handoff.get("source", "doris-schoolhouse"),
    }
    response = webhooks.post_multipart(handoff["target_url"], fields, "data", file_path)
    body = response.get("body", {}) if isinstance(response, dict) else {}
    body_obj = body[0] if isinstance(body, list) and body and isinstance(body[0], dict) else (body if isinstance(body, dict) else {})
    ok = bool(response.get("ok", False)) if isinstance(response, dict) else False
    updated = repo.update_recording(recording_id, {
        "status": "requeued" if ok else "requeue-error",
        "requeued_at": store.now(),
        "webhook_response": response,
        "transcription_status": "processing" if ok else "error",
        "summary_status": "processing" if ok else "error",
        "recording_paperless_document_id": body_obj.get("recording_paperless_document_id") or body_obj.get("document_id"),
    })
    return {"status": "ok" if ok else "error", "recording": updated or current, "handoff": handoff, "webhook": response}


@router.post("/{recording_id}/convert")
async def convert_recording(recording_id: str):
    recordings = repo.list_recordings()
    current = next((item for item in recordings if str(item.get("id")) == str(recording_id)), None)
    if not current:
        raise HTTPException(status_code=404, detail="Recording not found.")
    wav_path = current.get("stored_path")
    if not wav_path or not Path(wav_path).exists():
        raise HTTPException(status_code=400, detail="Source WAV file is missing.")
    mp3_path = current.get("mp3_path") or media.planned_mp3_path(wav_path)
    result = media.convert_wav_to_mp3(wav_path, mp3_path)
    updates = {
        "conversion_status": result["status"],
        "conversion_result": result,
        "updated_at": store.now(),
    }
    if result["status"] == "ok":
        updates["mp3_path"] = mp3_path
        updates["delete_source_result"] = media.delete_source_if_requested(wav_path, bool(current.get("delete_wav_after_success")))
        updates["status"] = "converted"
    updated = repo.update_recording(recording_id, updates)
    return {"status": result["status"], "recording": updated or current, "conversion": result}
