"""Output formatting for CLI results (Layer 2).

Formats structured SDK events for agent consumption.
"""

from __future__ import annotations

from typing import Any

from .client import StreamResult
from .parse import parse_json_field


def format_file_line(f: dict[str, Any]) -> str:
    """Format a single file as a one-line summary."""
    file_id: str = f.get('id', '?')
    name: str = f.get('name', '?')
    records = ', '.join(parse_json_field(f.get('records')))
    aggs = ', '.join(parse_json_field(f.get('aggregations')))
    freqs = ', '.join(parse_json_field(f.get('frequencies')))

    # Handle both JSONL event format and D1 format for date range
    dr = f.get('date_range')
    dr_min = f.get('date_range_min')
    dr_max = f.get('date_range_max')
    if dr and isinstance(dr, dict):
        date_str = f'{dr["min"][:7]} -> {dr["max"][:7]}'
    elif dr_min and dr_max:
        date_str = f'{str(dr_min)[:7]} -> {str(dr_max)[:7]}'
    else:
        date_str = '-'

    created_at = str(f.get('created_at', ''))[:16]  # "2026-03-17 23:47"
    parts = [f'  {file_id}', name, records, aggs, freqs, date_str]
    if created_at:
        parts.append(created_at)
    return '  '.join(parts)


def print_files_result(result: StreamResult, elapsed: float) -> int:
    """Format and print the files classification result. Returns exit code."""
    code = result.exit_code if result.exit_code is not None else 1

    if result.errors:
        for err in result.errors:
            print(f'error: {err}')
        print(f'[exit:{code} | {elapsed:.1f}s]')
        return code

    completed = result.get_event('FilesClassificationCompleted')
    failed = result.get_event('FilesClassificationFailed')

    if failed is not None:
        error: str = failed['data'].get('error', 'unknown error')
        print(f'error: classification failed — {error}')
        print(f'[exit:1 | {elapsed:.1f}s]')
        return 1

    if completed is not None:
        files: list[dict[str, Any]] = completed['data'].get('files', [])
        n = len(files)
        print(f'classified {n} file{"s" if n != 1 else ""}')
        for f in files:
            print(format_file_line(f))
    elif code != 0:
        if result.stderr.strip():
            print(f'error: {result.stderr.strip().splitlines()[-1]}')

    print(f'[exit:{code} | {elapsed:.1f}s]')
    return code


def _format_forecast_line(forecast: dict[str, Any], series_names: dict[str, str]) -> str:
    """Format a single forecast as a one-line summary."""
    fct_id: str = forecast.get('id', '?')
    series_id: str = forecast.get('series_id', '?')
    name = series_names.get(series_id, series_id)
    items: list[dict[str, Any]] = forecast.get('items', [])
    n_periods = len(items)

    if items:
        first_date = str(items[0].get('date', ''))[:7]
        last_date = str(items[-1].get('date', ''))[:7]
        date_str = f'{first_date} -> {last_date}'
    else:
        date_str = '-'

    return f'  {fct_id}  {name}  {n_periods} periods  {date_str}'


def print_forecast_result(result: StreamResult, elapsed: float) -> int:
    """Format and print the forecast result. Returns exit code."""
    code = result.exit_code if result.exit_code is not None else 1

    if result.errors:
        for err in result.errors:
            print(f'error: {err}')
        print(f'[exit:{code} | {elapsed:.1f}s]')
        return code

    # Print run_id header from ForecastingStarted
    started = result.get_event('ForecastingStarted')
    if started is not None and result.run_id:
        series_list: list[dict[str, Any]] = started['data'].get('series', [])
        n_series = len(series_list)
        print(f'{result.run_id}: forecasting {n_series} series')

    # Collect per-series failures
    failed_series: dict[str, str] = {}
    for ev in result.events:
        if ev['event'] in ('ForecastGenFailed', 'TargetDataFailed'):
            sid = ev['data'].get('series_id', '')
            name = ev['data'].get('series_name', sid)
            error = ev['data'].get('error', 'unknown error')
            failed_series[sid] = f'  \u2717  {name}  {error}'

    completed = result.get_event('ForecastingCompleted')

    if completed is not None:
        forecasts_data: list[dict[str, Any]] = completed['data'].get('forecasts', [])
        series_data: list[dict[str, Any]] = completed['data'].get('series', [])
        series_names = {s.get('id', ''): s.get('name', '') for s in series_data}

        for f in forecasts_data:
            print(_format_forecast_line(f, series_names))

        # Print failures for series not in the forecasts list
        forecasted_series = {f.get('series_id') for f in forecasts_data}
        for sid, line in failed_series.items():
            if sid not in forecasted_series:
                print(line)
    elif failed_series:
        for line in failed_series.values():
            print(line)
    elif code != 0:
        if result.stderr.strip():
            print(f'error: {result.stderr.strip().splitlines()[-1]}')

    print(f'[exit:{code} | {elapsed:.1f}s]')
    return code
