"""HTTP routes: health, config, transcribe, summarize."""

from __future__ import annotations

import asyncio
import json
import time

from aiohttp import web

from meeting_helper.state import state
from meeting_helper.server.websocket import ws_handler


async def health_handler(request: web.Request) -> web.Response:
    meeting_name = ""
    if state.meeting_info:
        meeting_name = getattr(state.meeting_info, "meeting_name", "") or ""
    return web.Response(
        text=json.dumps({
            "status": "ok",
            "meeting": meeting_name,
            "session_active": state.session_active,
            "uptime": round(time.time() - state.started_at) if state.started_at else 0,
        }),
        content_type="application/json",
    )


async def config_get_handler(request: web.Request) -> web.Response:
    """Return current workspace config."""
    config = request.app["config"]
    return web.Response(
        text=json.dumps({
            "repos": config.repos,
            "repos_workspaces": config.repos_workspaces,
            "repos_workspace": config.repos_workspace,  # compat
            "knowledge_paths": config.knowledge_paths,
            "knowledge_path": config.knowledge_path,    # compat
            "ignored_repos": config.ignored_repos,
            "ignored_knowledge": config.ignored_knowledge,
        }),
        content_type="application/json",
    )


async def config_post_handler(request: web.Request) -> web.Response:
    """Update workspace config mid-session. Rebuilds system prompt."""
    try:
        body = await request.json()
    except Exception:
        return web.Response(status=400, text='{"error": "invalid JSON"}',
                            content_type="application/json")

    config = request.app["config"]
    changed = False

    if "repos" in body:
        config.repos = body["repos"]
        changed = True
    if "repos_workspaces" in body:
        config.repos_workspaces = body["repos_workspaces"]
        changed = True
    elif "repos_workspace" in body:
        config.repos_workspace = body["repos_workspace"]
        changed = True
    if "knowledge_paths" in body:
        config.knowledge_paths = body["knowledge_paths"]
        changed = True
    elif "knowledge_path" in body:
        config.knowledge_path = body["knowledge_path"]
        changed = True
    if "ignored_repos" in body:
        config.ignored_repos = body["ignored_repos"]
    if "ignored_knowledge" in body:
        config.ignored_knowledge = body["ignored_knowledge"]
    # Broadcast so overlay refreshes chips immediately
    if "ignored_repos" in body or "ignored_knowledge" in body:
        from meeting_helper.server.websocket import broadcast
        asyncio.ensure_future(broadcast({
            "type": "config_changed",
            "ignored_repos": config.ignored_repos,
            "ignored_knowledge": config.ignored_knowledge,
        }))

    if changed:
        from meeting_helper.ai.prompts import build_system_prompt
        knowledge_folders = body.get("knowledge_folders")

        # Run file I/O in a thread so we don't block the event loop / audio pipeline
        if knowledge_folders is not None:
            from meeting_helper.context_loader import build_selective_context
            context_block = await asyncio.to_thread(
                build_selective_context, config.repos, config.knowledge_path, knowledge_folders
            )
        else:
            from meeting_helper.context_loader import build_full_context
            context_block = await asyncio.to_thread(
                build_full_context, config.repos, config.knowledge_paths or config.knowledge_path
            )
        state.system_prompt = build_system_prompt(context_block)

    return web.Response(
        text=json.dumps({"ok": True, "changed": changed}),
        content_type="application/json",
    )


async def transcript_handler_get(request: web.Request) -> web.Response:
    """GET /transcript — return the last N sentences from the buffer."""
    n = int(request.query.get("n", "10"))
    sentences = []
    if state.sentence_buffer is not None:
        sentences = state.sentence_buffer.get_last_n(n)
    interim = None
    if state.sentence_buffer is not None:
        interim = state.sentence_buffer.get_interim()
    return web.Response(
        text=json.dumps({"sentences": sentences, "interim": interim}),
        content_type="application/json",
    )


async def last_response_handler(request: web.Request) -> web.Response:
    """GET /last_response — return the last AI response text."""
    return web.Response(
        text=json.dumps({"text": state.last_response or ""}),
        content_type="application/json",
    )


async def query_handler(request: web.Request) -> web.Response:
    """POST /query — send a manual text query to Claude."""
    try:
        body = await request.json()
    except Exception:
        return web.Response(status=400, text='{"error": "invalid JSON"}',
                            content_type="application/json")

    text = body.get("text", "").strip()
    if not text:
        return web.Response(status=400, text='{"error": "text required"}',
                            content_type="application/json")

    from meeting_helper.ai.client import handle_manual_query
    config = request.app["config"]

    try:
        await handle_manual_query(state, config, text)
        return web.Response(
            text=json.dumps({"ok": True}),
            content_type="application/json",
        )
    except Exception as exc:
        return web.Response(
            status=500,
            text=json.dumps({"error": str(exc)}),
            content_type="application/json",
        )


async def transcribe_handler(request: web.Request) -> web.Response:
    """POST /transcribe — transcribe an MP3 file with Whisper."""
    try:
        body = await request.json()
    except Exception:
        return web.Response(status=400, text='{"error": "invalid JSON"}',
                            content_type="application/json")

    mp3_path = body.get("mp3_path", "")
    if not mp3_path:
        return web.Response(status=400, text='{"error": "mp3_path required"}',
                            content_type="application/json")

    from meeting_helper.ai.client import transcribe_audio_file
    config = request.app["config"]

    try:
        transcript = await asyncio.to_thread(transcribe_audio_file, mp3_path, config)
        return web.Response(
            text=json.dumps({"ok": True, "transcript": transcript}),
            content_type="application/json",
        )
    except Exception as exc:
        return web.Response(
            status=500,
            text=json.dumps({"error": str(exc)}),
            content_type="application/json",
        )


async def summarize_handler(request: web.Request) -> web.Response:
    """POST /summarize — summarize a transcript with Claude."""
    try:
        body = await request.json()
    except Exception:
        return web.Response(status=400, text='{"error": "invalid JSON"}',
                            content_type="application/json")

    transcript_path = body.get("transcript_path", "")
    if not transcript_path:
        return web.Response(status=400, text='{"error": "transcript_path required"}',
                            content_type="application/json")

    from meeting_helper.ai.client import summarize_transcript
    config = request.app["config"]

    try:
        summary = await summarize_transcript(transcript_path, config)
        return web.Response(
            text=json.dumps({"ok": True, "summary": summary}),
            content_type="application/json",
        )
    except Exception as exc:
        return web.Response(
            status=500,
            text=json.dumps({"error": str(exc)}),
            content_type="application/json",
        )


async def knowledge_tree_handler(request: web.Request) -> web.Response:
    """GET /knowledge-tree — return folder structure of the knowledge base."""
    config = request.app["config"]
    if not config.knowledge_path:
        return web.Response(
            text=json.dumps({"tree": []}), content_type="application/json"
        )
    from meeting_helper.context_loader import get_knowledge_tree
    tree = get_knowledge_tree(config.knowledge_path)
    return web.Response(
        text=json.dumps({"tree": tree}), content_type="application/json"
    )


async def ignore_handler(request: web.Request) -> web.Response:
    """POST /ignore — add or remove a repo/knowledge folder from the ignore list.

    Body: {"type": "repo"|"knowledge", "name": "folder_name", "action": "add"|"remove"}
    """
    try:
        body = await request.json()
    except Exception:
        return web.Response(status=400, text='{"error": "invalid JSON"}', content_type="application/json")

    config = request.app["config"]
    item_type = body.get("type")  # "repo" or "knowledge"
    name = body.get("name", "").strip()
    action = body.get("action", "add")  # "add" or "remove"

    if not name or item_type not in ("repo", "knowledge"):
        return web.Response(status=400, text='{"error": "type and name required"}', content_type="application/json")

    if item_type == "repo":
        lst = list(config.ignored_repos)
        if action == "add" and name not in lst:
            lst.append(name)
        elif action == "remove":
            lst = [x for x in lst if x != name]
        config.ignored_repos = lst
    else:
        lst = list(config.ignored_knowledge)
        if action == "add" and name not in lst:
            lst.append(name)
        elif action == "remove":
            lst = [x for x in lst if x != name]
        config.ignored_knowledge = lst

    # config is AppConfig (dataclass) — no save() method. Disk write happens in GUI.
    return web.Response(
        text=json.dumps({"ok": True, "ignored_repos": config.ignored_repos, "ignored_knowledge": config.ignored_knowledge}),
        content_type="application/json",
    )


async def auto_context_handler(request: web.Request) -> web.Response:
    """GET /auto-context — return current auto-context state."""
    return web.Response(
        text=json.dumps({
            "index_loaded": bool(state.auto_context_index),
            "index_len": len(state.auto_context_index),
            "selection": state.auto_context_selection,
        }),
        content_type="application/json",
    )


async def proactive_handler(request: web.Request) -> web.Response:
    """POST /proactive — enable or disable proactive answers for current session."""
    try:
        body = await request.json()
    except Exception:
        return web.Response(status=400, text='{"error": "invalid JSON"}', content_type="application/json")

    enabled = bool(body.get("enabled", True))
    monitor = state.proactive_monitor
    if monitor is not None:
        monitor.set_enabled(enabled)
    auto_ctx = state.auto_context_selector
    if auto_ctx is not None:
        auto_ctx.set_enabled(enabled)

    return web.Response(
        text=json.dumps({"ok": True, "enabled": enabled, "monitor_active": monitor is not None}),
        content_type="application/json",
    )


async def proactive_status_handler(request: web.Request) -> web.Response:
    """GET /proactive — return current proactive enabled state."""
    monitor = state.proactive_monitor
    enabled = monitor.is_enabled() if monitor is not None else False
    return web.Response(
        text=json.dumps({"enabled": enabled, "monitor_active": monitor is not None}),
        content_type="application/json",
    )


def setup_routes(app: web.Application) -> None:
    app.router.add_get("/health", health_handler)
    app.router.add_get("/config", config_get_handler)
    app.router.add_post("/config", config_post_handler)
    app.router.add_get("/knowledge-tree", knowledge_tree_handler)
    app.router.add_get("/transcript", transcript_handler_get)
    app.router.add_get("/last_response", last_response_handler)
    app.router.add_post("/query", query_handler)
    app.router.add_post("/transcribe", transcribe_handler)
    app.router.add_post("/summarize", summarize_handler)
    app.router.add_post("/ignore", ignore_handler)
    app.router.add_get("/auto-context", auto_context_handler)
    app.router.add_post("/proactive", proactive_handler)
    app.router.add_get("/proactive", proactive_status_handler)
    app.router.add_get("/ws", ws_handler)
