"""crondag logs — view task logs."""
from __future__ import annotations

import asyncio
import json
import sys

import click

from crondag.config import get_settings


@click.command()
@click.argument("dag_id")
@click.argument("run_id", required=False)
@click.argument("task_id", required=False)
@click.option("-f", "--follow", is_flag=True, help="Follow log output")
@click.option("-o", "--output-format", type=click.Choice(["text", "json"]), default="text")
def logs(dag_id: str, run_id: str | None, task_id: str | None, follow: bool, output_format: str):
    """View task logs.

    Usage:
        crondag logs <dag_id>                    # Logs from latest run
        crondag logs <dag_id> <run_id>           # Logs from specific run
        crondag logs <dag_id> <run_id> <task_id> # Logs from specific task
    """
    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 crondag.models.log import TaskLogModel
        from sqlalchemy import select

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

        async with session_factory() as session:
            # If no run_id, get the latest run
            if not run_id:
                result = await session.execute(
                    select(DagRunModel)
                    .where(DagRunModel.dag_id == dag_id)
                    .order_by(DagRunModel.created_at.desc())
                    .limit(1)
                )
                latest = result.scalar_one_or_none()
                if not latest:
                    click.echo(f"No runs found for DAG '{dag_id}'.", err=True)
                    sys.exit(1)
                actual_run_id = latest.run_id
            else:
                actual_run_id = run_id

            # Get task instances
            ti_query = select(TaskInstanceModel).where(
                TaskInstanceModel.dag_id == dag_id,
                TaskInstanceModel.run_id == actual_run_id,
            )
            if task_id:
                ti_query = ti_query.where(TaskInstanceModel.task_id == task_id)

            ti_result = await session.execute(ti_query)
            task_instances = ti_result.scalars().all()

            if not task_instances:
                click.echo(f"No task instances found.", err=True)
                sys.exit(1)

            ti_ids = [ti.id for ti in task_instances]
            ti_map = {ti.id: ti.task_id for ti in task_instances}

            # Get logs
            log_result = await session.execute(
                select(TaskLogModel)
                .where(TaskLogModel.task_instance_id.in_(ti_ids))
                .order_by(TaskLogModel.timestamp, TaskLogModel.line_number)
            )
            log_entries = log_result.scalars().all()

            data = [
                {
                    "task_id": ti_map.get(l.task_instance_id, "?"),
                    "timestamp": str(l.timestamp),
                    "level": l.level,
                    "message": l.message,
                }
                for l in log_entries
            ]

        if output_format == "json":
            click.echo(json.dumps(data, indent=2, default=str))
        else:
            if not data:
                # Show task instance info even without logs
                for ti in task_instances:
                    click.echo(f"[{ti.task_id}] state={ti.state} error={ti.error or 'none'}")
                return
            for d in data:
                click.echo(f"[{d['timestamp']}] [{d['level']}] {d['task_id']}: {d['message']}")

    asyncio.run(_run())
