"""Replay management endpoints — JSONL files, teaching, test replay, speed control.

Mirrors the replay management features from AI_Photographer/Server/photo_server.py.
"""

from __future__ import annotations

import asyncio

from fastapi import APIRouter, HTTPException, UploadFile, File
from fastapi.responses import FileResponse
from pydantic import BaseModel

from Project.Sanad.config import MOTIONS_DIR
from Project.Sanad.core.logger import get_logger
from Project.Sanad.dashboard.routes._safe_io import (
    safe_path_under, check_upload_size, atomic_write_bytes,
)

log = get_logger("replay_route")
router = APIRouter()


# -- models --

class ReplayRequest(BaseModel):
    name: str
    speed: float = 1.0

class RenameRequest(BaseModel):
    old_name: str
    new_name: str

class TeachRequest(BaseModel):
    name: str
    duration_sec: float = 15.0


# -- motion file CRUD --

@router.get("/files")
async def list_motion_files():
    from Project.Sanad.main import arm
    return {"files": arm.list_motion_files()}


@router.get("/files/{filename}")
async def download_motion_file(filename: str):
    path = safe_path_under(MOTIONS_DIR, filename)
    if not path.exists():
        raise HTTPException(404, "File not found.")
    return FileResponse(path, filename=path.name, media_type="application/json")


@router.post("/files/upload")
async def upload_motion_file(file: UploadFile = File(...)):
    if not file.filename or not file.filename.lower().endswith(".jsonl"):
        raise HTTPException(400, "Only .jsonl files accepted.")
    MOTIONS_DIR.mkdir(parents=True, exist_ok=True)
    dest = safe_path_under(MOTIONS_DIR, file.filename)
    content = await file.read()
    check_upload_size(content)
    atomic_write_bytes(dest, content)
    return {"ok": True, "name": dest.name, "size_bytes": len(content)}


@router.post("/files/rename")
async def rename_motion_file(payload: RenameRequest):
    old = safe_path_under(MOTIONS_DIR, payload.old_name)
    new = safe_path_under(MOTIONS_DIR, payload.new_name)
    if not old.exists():
        raise HTTPException(404, f"File not found: {payload.old_name}")
    if new.exists():
        raise HTTPException(409, f"File already exists: {payload.new_name}")
    old.rename(new)
    return {"ok": True, "old_name": old.name, "new_name": new.name}


@router.delete("/files/{filename}")
async def delete_motion_file(filename: str):
    path = safe_path_under(MOTIONS_DIR, filename)
    if not path.exists():
        raise HTTPException(404, "File not found.")
    path.unlink()
    return {"ok": True, "deleted": path.name}


# -- test replay --

_BG_TASKS: set[asyncio.Task] = set()


@router.post("/test")
async def test_replay(payload: ReplayRequest):
    """Test-play a motion file at the given speed."""
    from Project.Sanad.main import arm
    if arm.is_busy:
        raise HTTPException(409, "Arm is busy.")
    path = safe_path_under(MOTIONS_DIR, payload.name)
    if not path.exists():
        raise HTTPException(404, f"Motion file not found: {path.name}")

    async def _run():
        try:
            await asyncio.to_thread(arm.replay_file, str(path), payload.speed)
        except Exception:
            log.exception("Test replay failed")

    task = asyncio.create_task(_run())
    _BG_TASKS.add(task)
    task.add_done_callback(_BG_TASKS.discard)
    return {"ok": True, "name": path.name, "speed": payload.speed}


@router.post("/cancel")
async def cancel_replay():
    """Stop the current replay — the smooth return-to-home runs as the
    final phase of the replay itself.

    Matches g1_replay_v4_stable.py's behaviour: the play loop breaks on
    the cancel flag, then the same Run() function executes its
    return-home ramp + DisableSDK. No separate scheduling needed.
    """
    from Project.Sanad.main import arm
    arm.cancel()
    return {"ok": True, "message": "Cancelled — returning to home pose smoothly."}


@router.get("/status")
async def replay_status():
    from Project.Sanad.main import arm, teacher
    return {
        "arm": arm.status(),
        "teaching": teacher.status() if teacher else {},
    }


# -- teaching mode --

@router.post("/teach/start")
async def start_teaching(payload: TeachRequest):
    from Project.Sanad.main import teacher
    if teacher is None:
        raise HTTPException(503, "Teaching module not available.")
    if teacher.is_recording:
        raise HTTPException(409, "Teaching session already active.")
    existing = MOTIONS_DIR / f"{payload.name}.jsonl"
    if existing.exists():
        raise HTTPException(409, f"Motion file already exists: {payload.name}.jsonl")
    return teacher.start(payload.name, payload.duration_sec)


@router.post("/teach/stop")
async def stop_teaching():
    from Project.Sanad.main import teacher
    if teacher is None:
        raise HTTPException(503, "Teaching module not available.")
    return teacher.stop()


@router.get("/teach/status")
async def teaching_status():
    from Project.Sanad.main import teacher
    if teacher is None:
        return {"recording": False, "phase": "idle"}
    return teacher.status()
