"""Web UI routes using Jinja2 + HTMX."""
from __future__ import annotations

import json
from pathlib import Path

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy import select

from crondag.models.base import get_session_factory
from crondag.models.dag import DagModel
from crondag.models.dag_run import DagRunModel
from crondag.models.task_instance import TaskInstanceModel
from crondag.models.log import TaskLogModel

TEMPLATE_DIR = Path(__file__).parent / "templates"
templates = Jinja2Templates(directory=str(TEMPLATE_DIR))


def setup_ui_routes(app: FastAPI):
    """Register UI routes on the FastAPI app."""

    @app.get("/", response_class=HTMLResponse)
    async def root(request: Request):
        """Redirect to DAGs list."""
        from fastapi.responses import RedirectResponse
        return RedirectResponse(url="/ui/dags")

    @app.get("/ui/dags", response_class=HTMLResponse)
    async def ui_dags(request: Request):
        """DAGs list page."""
        session_factory = get_session_factory()
        async with session_factory() as session:
            result = await session.execute(select(DagModel).order_by(DagModel.dag_id))
            dags = result.scalars().all()
            dag_list = []
            for d in dags:
                # Get latest run state
                run_result = await session.execute(
                    select(DagRunModel)
                    .where(DagRunModel.dag_id == d.dag_id)
                    .order_by(DagRunModel.created_at.desc())
                    .limit(1)
                )
                latest_run = run_result.scalar_one_or_none()
                dag_list.append({
                    "dag_id": d.dag_id,
                    "description": d.description,
                    "is_paused": d.is_paused,
                    "schedule": f"{d.schedule_value}" if d.schedule_value else "Manual",
                    "schedule_type": d.schedule_type,
                    "next_run_at": d.next_run_at,
                    "tags": json.loads(d.tags) if d.tags else [],
                    "last_run_state": latest_run.state if latest_run else None,
                    "last_run_date": latest_run.logical_date if latest_run else None,
                })

        return templates.TemplateResponse("dags.html", {
            "request": request,
            "dags": dag_list,
        })

    @app.get("/ui/dags/{dag_id}", response_class=HTMLResponse)
    async def ui_dag_detail(request: Request, dag_id: str):
        """DAG detail page."""
        session_factory = get_session_factory()
        async with session_factory() as session:
            dag = await session.get(DagModel, dag_id)
            if not dag:
                return HTMLResponse("<h1>DAG not found</h1>", status_code=404)

            runs_result = await session.execute(
                select(DagRunModel)
                .where(DagRunModel.dag_id == dag_id)
                .order_by(DagRunModel.created_at.desc())
                .limit(20)
            )
            runs = runs_result.scalars().all()

            # Build task graph for mermaid
            scheduler = getattr(request.app.state, "scheduler", None)
            task_ids = []
            dep_map = {}
            if scheduler and dag_id in scheduler.dag_bag.dags:
                dag_obj = scheduler.dag_bag.dags[dag_id]
                task_ids = dag_obj.get_task_ids()
                dep_map = dag_obj.get_dependency_map()

        return templates.TemplateResponse("dag_detail.html", {
            "request": request,
            "dag": dag,
            "runs": runs,
            "task_ids": task_ids,
            "dep_map": dep_map,
        })

    @app.get("/ui/runs/{run_id}", response_class=HTMLResponse)
    async def ui_run_detail(request: Request, run_id: str):
        """Run detail page."""
        session_factory = get_session_factory()
        async with session_factory() as session:
            result = await session.execute(
                select(DagRunModel).where(DagRunModel.run_id == run_id)
            )
            run = result.scalar_one_or_none()
            if not run:
                return HTMLResponse("<h1>Run not found</h1>", status_code=404)

            ti_result = await session.execute(
                select(TaskInstanceModel)
                .where(
                    TaskInstanceModel.dag_id == run.dag_id,
                    TaskInstanceModel.run_id == run.run_id,
                )
                .order_by(TaskInstanceModel.id)
            )
            tasks = ti_result.scalars().all()

        return templates.TemplateResponse("run_detail.html", {
            "request": request,
            "run": run,
            "tasks": tasks,
        })

    @app.get("/ui/tasks/{ti_id}/log", response_class=HTMLResponse)
    async def ui_task_log(request: Request, ti_id: int):
        """Task log viewer page."""
        session_factory = get_session_factory()
        async with session_factory() as session:
            ti = await session.get(TaskInstanceModel, ti_id)
            if not ti:
                return HTMLResponse("<h1>Task not found</h1>", status_code=404)

            log_result = await session.execute(
                select(TaskLogModel)
                .where(TaskLogModel.task_instance_id == ti_id)
                .order_by(TaskLogModel.timestamp, TaskLogModel.line_number)
            )
            logs = log_result.scalars().all()

        return templates.TemplateResponse("task_log.html", {
            "request": request,
            "task": ti,
            "logs": logs,
        })

    # HTMX partial: refreshable DAGs table body
    @app.get("/ui/partials/dags-table", response_class=HTMLResponse)
    async def ui_dags_table_partial(request: Request):
        """HTMX partial for DAGs table auto-refresh."""
        session_factory = get_session_factory()
        async with session_factory() as session:
            result = await session.execute(select(DagModel).order_by(DagModel.dag_id))
            dags = result.scalars().all()
            dag_list = []
            for d in dags:
                run_result = await session.execute(
                    select(DagRunModel)
                    .where(DagRunModel.dag_id == d.dag_id)
                    .order_by(DagRunModel.created_at.desc())
                    .limit(1)
                )
                latest_run = run_result.scalar_one_or_none()
                dag_list.append({
                    "dag_id": d.dag_id,
                    "description": d.description,
                    "is_paused": d.is_paused,
                    "schedule": f"{d.schedule_value}" if d.schedule_value else "Manual",
                    "schedule_type": d.schedule_type,
                    "next_run_at": d.next_run_at,
                    "tags": json.loads(d.tags) if d.tags else [],
                    "last_run_state": latest_run.state if latest_run else None,
                    "last_run_date": latest_run.logical_date if latest_run else None,
                })

        return templates.TemplateResponse("partials/dags_table.html", {
            "request": request,
            "dags": dag_list,
        })
