"""crondag runs — run management commands."""
from __future__ import annotations

import asyncio
import json
import sys

import click

from crondag.config import get_settings


@click.group()
def runs():
    """Run management commands."""
    pass


@runs.command("list")
@click.argument("dag_id")
@click.option("-o", "--output-format", type=click.Choice(["text", "json"]), default="text")
@click.option("--limit", default=10, help="Number of runs to show")
def runs_list(dag_id: str, output_format: str, limit: int):
    """List runs for a DAG."""
    async def _run():
        settings = get_settings()
        from crondag.models.base import get_session_factory, get_engine
        from crondag.models.dag_run import DagRunModel
        from sqlalchemy import select

        get_engine(settings.database_url)
        session_factory = get_session_factory(settings.database_url)

        async with session_factory() as session:
            result = await session.execute(
                select(DagRunModel)
                .where(DagRunModel.dag_id == dag_id)
                .order_by(DagRunModel.created_at.desc())
                .limit(limit)
            )
            dag_runs = result.scalars().all()

            data = [
                {
                    "run_id": r.run_id,
                    "state": r.state,
                    "run_type": r.run_type,
                    "logical_date": str(r.logical_date),
                    "start_date": str(r.start_date),
                    "end_date": str(r.end_date),
                    "duration": (
                        f"{(r.end_date - r.start_date).total_seconds():.1f}s"
                        if r.start_date and r.end_date else None
                    ),
                }
                for r in dag_runs
            ]

        if output_format == "json":
            click.echo(json.dumps(data, indent=2, default=str))
        else:
            if not data:
                click.echo(f"No runs found for DAG '{dag_id}'.")
                return
            for d in data:
                state_icon = {"success": "\u2713", "failed": "\u2717", "running": "\u27f3", "queued": "\u25cb"}.get(d["state"], "?")
                click.echo(f"  {state_icon} {d['run_id']}  {d['state']}  {d['logical_date']}"
                          + (f"  {d['duration']}" if d['duration'] else ""))

    asyncio.run(_run())


@runs.command("latest")
@click.argument("dag_id")
@click.option("-o", "--output-format", type=click.Choice(["text", "json"]), default="text")
def runs_latest(dag_id: str, output_format: str):
    """Show the latest run for a DAG."""
    async def _run():
        settings = get_settings()
        from crondag.models.base import get_session_factory, get_engine
        from crondag.models.dag_run import DagRunModel
        from crondag.models.task_instance import TaskInstanceModel
        from sqlalchemy import select

        get_engine(settings.database_url)
        session_factory = get_session_factory(settings.database_url)

        async with session_factory() as session:
            result = await session.execute(
                select(DagRunModel)
                .where(DagRunModel.dag_id == dag_id)
                .order_by(DagRunModel.created_at.desc())
                .limit(1)
            )
            dag_run = result.scalar_one_or_none()

            if not dag_run:
                click.echo(f"No runs found for DAG '{dag_id}'.", err=True)
                sys.exit(1)

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

            data = {
                "dag_id": dag_id,
                "run_id": dag_run.run_id,
                "state": dag_run.state,
                "run_type": dag_run.run_type,
                "logical_date": str(dag_run.logical_date),
                "start_date": str(dag_run.start_date),
                "end_date": str(dag_run.end_date),
                "tasks": [
                    {
                        "task_id": ti.task_id,
                        "state": ti.state,
                        "try_number": ti.try_number,
                        "duration": ti.duration,
                        "error": ti.error,
                    }
                    for ti in tasks
                ],
            }

        if output_format == "json":
            click.echo(json.dumps(data, indent=2, default=str))
        else:
            click.echo(f"DAG: {dag_id}")
            click.echo(f"Run: {data['run_id']}  State: {data['state']}")
            click.echo(f"Started: {data['start_date']}  Ended: {data['end_date']}")
            for t in data["tasks"]:
                icon = "\u2713" if t["state"] == "success" else "\u2717" if t["state"] == "failed" else "\u25cb"
                click.echo(f"  {icon} {t['task_id']}: {t['state']}"
                          + (f" ({t['duration']:.1f}s)" if t['duration'] else ""))

    asyncio.run(_run())


@runs.command("active")
@click.option("-o", "--output-format", type=click.Choice(["text", "json"]), default="text")
def runs_active(output_format: str):
    """Show all active (running/queued) runs."""
    async def _run():
        settings = get_settings()
        from crondag.models.base import get_session_factory, get_engine
        from crondag.models.dag_run import DagRunModel
        from crondag.sdk.state import DagRunState
        from sqlalchemy import select

        get_engine(settings.database_url)
        session_factory = get_session_factory(settings.database_url)

        async with session_factory() as session:
            result = await session.execute(
                select(DagRunModel)
                .where(DagRunModel.state.in_([DagRunState.QUEUED, DagRunState.RUNNING]))
                .order_by(DagRunModel.created_at.desc())
            )
            active_runs = result.scalars().all()

            data = [
                {
                    "dag_id": r.dag_id,
                    "run_id": r.run_id,
                    "state": r.state,
                    "start_date": str(r.start_date),
                }
                for r in active_runs
            ]

        if output_format == "json":
            click.echo(json.dumps(data, indent=2, default=str))
        else:
            if not data:
                click.echo("No active runs.")
                return
            for d in data:
                click.echo(f"  {d['dag_id']}  {d['run_id']}  {d['state']}  {d['start_date']}")

    asyncio.run(_run())
