from __future__ import annotations

from fastapi import APIRouter, Depends, Request
from fastapi.responses import JSONResponse

from app_dependencies import get_runtime
from message_pipeline import typed_message_from_api_notification
from nanobot_api_client import run_nanobot_agent_turn
from route_helpers import read_json_request
from web_runtime import WebAppRuntime

router = APIRouter()


@router.get("/inbox")
async def get_inbox(
    request: Request, runtime: WebAppRuntime = Depends(get_runtime)
) -> JSONResponse:
    status_filter = str(request.query_params.get("status", "") or "").strip() or None
    kind_filter = str(request.query_params.get("kind", "") or "").strip() or None
    include_closed = str(request.query_params.get("include_closed", "") or "").strip().lower() in {
        "1",
        "true",
        "yes",
        "on",
    }
    limit_raw = str(request.query_params.get("limit", "") or "").strip()
    try:
        limit = max(1, min(int(limit_raw), 50)) if limit_raw else None
    except ValueError:
        return JSONResponse({"error": "limit must be an integer"}, status_code=400)

    tags_raw = request.query_params.getlist("tag")
    tags: list[str] = []
    for raw in tags_raw:
        for part in str(raw).split(","):
            part_clean = part.strip()
            if part_clean:
                tags.append(part_clean)

    try:
        items = runtime.inbox_service.list_items(
            status_filter=status_filter,
            kind_filter=kind_filter,
            include_closed=include_closed,
            limit=limit,
            tags=tags,
        )
    except ValueError as exc:
        return JSONResponse({"error": str(exc)}, status_code=400)
    except Exception as exc:
        return JSONResponse({"error": f"failed to load inbox: {exc}"}, status_code=500)
    return JSONResponse({"items": items})


@router.post("/inbox/capture")
async def capture_inbox_item(
    request: Request,
    runtime: WebAppRuntime = Depends(get_runtime),
) -> JSONResponse:
    try:
        payload = await read_json_request(request)
    except ValueError as exc:
        return JSONResponse({"error": str(exc)}, status_code=400)

    title = str(payload.get("title", "") or "")
    text = str(payload.get("text", "") or "")
    kind = str(payload.get("kind", "unknown") or "unknown")
    source = str(payload.get("source", "web-ui") or "web-ui")
    due = str(payload.get("due", "") or "")
    body = str(payload.get("body", "") or "")
    session_id = str(payload.get("session_id", "") or "")
    raw_tags = payload.get("tags", [])
    tags = [str(tag) for tag in raw_tags] if isinstance(raw_tags, list) else []
    confidence_value = payload.get("confidence")
    confidence = confidence_value if isinstance(confidence_value, (int, float)) else None

    try:
        item = runtime.inbox_service.capture_item(
            title=title,
            text=text,
            kind=kind,
            source=source,
            due=due,
            body=body,
            session_id=session_id,
            tags=tags,
            confidence=confidence,
        )
    except ValueError as exc:
        return JSONResponse({"error": str(exc)}, status_code=400)
    except Exception as exc:
        return JSONResponse({"error": f"failed to capture inbox item: {exc}"}, status_code=500)

    await runtime.publish_inbox_changed()
    return JSONResponse({"status": "ok", "item": item}, status_code=201)


@router.post("/inbox/accept-task")
async def accept_inbox_item_as_task(
    request: Request,
    runtime: WebAppRuntime = Depends(get_runtime),
) -> JSONResponse:
    try:
        payload = await read_json_request(request)
    except ValueError as exc:
        return JSONResponse({"error": str(exc)}, status_code=400)

    item = str(payload.get("item", "") or "").strip()
    lane = str(payload.get("lane", "backlog") or "backlog").strip()
    title = str(payload.get("title", "") or "")
    due = str(payload.get("due", "") or "")
    body = payload.get("body")
    body_text = str(body) if isinstance(body, str) else None
    raw_tags = payload.get("tags")
    tags = [str(tag) for tag in raw_tags] if isinstance(raw_tags, list) else None

    if not item:
        return JSONResponse({"error": "item is required"}, status_code=400)

    try:
        result = await runtime.inbox_service.accept_item_as_task(
            item=item,
            lane=lane,
            title=title,
            due=due,
            body_text=body_text,
            tags=tags,
            run_nanobot_turn=run_nanobot_agent_turn,
            notification_to_event=lambda obj: typed_message_from_api_notification(
                obj,
                default_chat_id="inbox-groomer",
            ),
        )
    except (FileNotFoundError, ValueError) as exc:
        return JSONResponse({"error": str(exc)}, status_code=400)
    except RuntimeError as exc:
        return JSONResponse({"error": str(exc)}, status_code=503)
    except Exception as exc:
        return JSONResponse({"error": f"failed to accept inbox item: {exc}"}, status_code=500)

    await runtime.publish_inbox_changed()
    await runtime.publish_cards_changed()
    return JSONResponse(result)


@router.post("/inbox/dismiss")
async def dismiss_inbox_item(
    request: Request,
    runtime: WebAppRuntime = Depends(get_runtime),
) -> JSONResponse:
    try:
        payload = await read_json_request(request)
    except ValueError as exc:
        return JSONResponse({"error": str(exc)}, status_code=400)

    item = str(payload.get("item", "") or "").strip()
    if not item:
        return JSONResponse({"error": "item is required"}, status_code=400)

    try:
        item_payload = runtime.inbox_service.dismiss_item(item)
    except (FileNotFoundError, ValueError) as exc:
        return JSONResponse({"error": str(exc)}, status_code=400)
    except Exception as exc:
        return JSONResponse({"error": f"failed to dismiss inbox item: {exc}"}, status_code=500)

    await runtime.publish_inbox_changed()
    return JSONResponse({"status": "ok", "item": item_payload})
