"""DAG API routes."""
from __future__ import annotations

import json
from datetime import datetime, timezone

from fastapi import APIRouter, HTTPException, Request
from pydantic import BaseModel
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

router = APIRouter(tags=["dags"])


class DagResponse(BaseModel):
    dag_id: str
    description: str
    schedule_type: str | None
    schedule_value: str | None
    is_paused: bool
    fileloc: str
    next_run_at: str | None
    tags: list[str]

    model_config = {"from_attributes": True}


class TriggerRequest(BaseModel):
    conf: dict | None = None


@router.get("/dags")
async def list_dags(request: Request):
    """List all DAGs."""
    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()
        return [
            {
                "dag_id": d.dag_id,
                "description": d.description,
                "schedule_type": d.schedule_type,
                "schedule_value": d.schedule_value,
                "is_paused": d.is_paused,
                "fileloc": d.fileloc,
                "next_run_at": str(d.next_run_at) if d.next_run_at else None,
                "tags": json.loads(d.tags) if d.tags else [],
            }
            for d in dags
        ]


@router.get("/dags/{dag_id}")
async def get_dag(dag_id: str):
    """Get DAG details."""
    session_factory = get_session_factory()
    async with session_factory() as session:
        dag = await session.get(DagModel, dag_id)
        if not dag:
            raise HTTPException(status_code=404, detail=f"DAG '{dag_id}' not found")
        return {
            "dag_id": dag.dag_id,
            "description": dag.description,
            "schedule_type": dag.schedule_type,
            "schedule_value": dag.schedule_value,
            "is_paused": dag.is_paused,
            "fileloc": dag.fileloc,
            "next_run_at": str(dag.next_run_at) if dag.next_run_at else None,
            "last_parsed_at": str(dag.last_parsed_at) if dag.last_parsed_at else None,
            "tags": json.loads(dag.tags) if dag.tags else [],
        }


@router.post("/dags/{dag_id}/trigger")
async def trigger_dag(dag_id: str, request: Request, body: TriggerRequest | None = None):
    """Trigger a DAG run."""
    scheduler = request.app.state.scheduler
    if not scheduler:
        raise HTTPException(status_code=503, detail="Scheduler not available")

    conf = body.conf if body else None
    dag_run = await scheduler.trigger_dag(dag_id, conf)
    if not dag_run:
        raise HTTPException(status_code=404, detail=f"DAG '{dag_id}' not found")

    return {
        "dag_id": dag_id,
        "run_id": dag_run.run_id,
        "state": dag_run.state,
        "logical_date": str(dag_run.logical_date),
    }


@router.post("/dags/{dag_id}/pause")
async def pause_dag(dag_id: str):
    """Pause a DAG."""
    session_factory = get_session_factory()
    async with session_factory() as session:
        dag = await session.get(DagModel, dag_id)
        if not dag:
            raise HTTPException(status_code=404, detail=f"DAG '{dag_id}' not found")
        dag.is_paused = True
        await session.commit()
    return {"dag_id": dag_id, "is_paused": True}


@router.post("/dags/{dag_id}/unpause")
async def unpause_dag(dag_id: str):
    """Unpause a DAG."""
    session_factory = get_session_factory()
    async with session_factory() as session:
        dag = await session.get(DagModel, dag_id)
        if not dag:
            raise HTTPException(status_code=404, detail=f"DAG '{dag_id}' not found")
        dag.is_paused = False
        await session.commit()
    return {"dag_id": dag_id, "is_paused": False}
