from __future__ import annotations

import asyncio

import typer
from scraper2_hj3415.cli.common import (
    ArgCode,
    ArgEndpoint,
    OptAsOf,
    OptChunk,
    OptLimit,
    OptShow,
    OptUniverse,
    build_cli_usecases,
    ensure_non_empty_code,
    get_cli_settings,
    get_ingest_uc,
    iter_endpoints,
    load_universe_codes,
    parse_asof,
    pretty,
    run_ingest_many_with_progress,
)

app = typer.Typer(no_args_is_help=True, help="NFS 수집/저장")


@app.command("one")
def nfs_one(
    code: ArgCode,
    endpoint: ArgEndpoint,
    show: OptShow = True,
    asof: OptAsOf = None,
) -> None:
    """
    단일 종목에 대해 지정 endpoint를 수집/저장한다.
    """
    resolved_code = ensure_non_empty_code(code)
    settings = get_cli_settings()
    resolved_sink = settings.nfs_sink
    resolved_sleep_sec = settings.scraper_sleep_sec_default

    if resolved_sink == "memory" and not show:
        typer.echo("memory sink에서는 출력 결과를 항상 보여줍니다.")
        show = True

    endpoints = iter_endpoints(endpoint)
    run_asof = parse_asof(asof)

    async def _run() -> None:
        ucs = build_cli_usecases(nfs_sink=resolved_sink)
        try:
            if resolved_sink == "mongo":
                await ucs.resources.bootstrap()

            for ep in endpoints:
                ingest_uc = get_ingest_uc(ucs, ep)
                env = await ingest_uc.execute(
                    resolved_code,
                    sleep_sec=resolved_sleep_sec,
                    asof=run_asof,
                )

                typer.echo(f"\n=== ONE DONE: {ep} {resolved_code} ===")
                if show:
                    typer.echo(pretty(env))
        finally:
            await ucs.resources.aclose()

    asyncio.run(_run())


@app.command("all")
def nfs_all(
    endpoint: ArgEndpoint,
    universe: OptUniverse = "krx300",
    limit: OptLimit = 0,
    chunk_size: OptChunk = 5,
    asof: OptAsOf = None,
) -> None:
    """
    유니버스 전체 종목에 대해 지정 endpoint를 수집/저장한다.
    """
    settings = get_cli_settings()
    resolved_sink = settings.nfs_sink
    resolved_sleep_sec = settings.scraper_sleep_sec_default

    endpoints = iter_endpoints(endpoint)
    run_asof = parse_asof(asof)

    if endpoint.strip().lower() == "c104":
        typer.echo("C104는 수집 속도가 느려 chunk_size를 3으로 설정합니다.")
        chunk_size = 3

    async def _run() -> None:
        ucs = build_cli_usecases(nfs_sink=resolved_sink)
        try:
            await ucs.resources.bootstrap()

            codes = await load_universe_codes(
                ucs=ucs,
                universe=universe,
                limit=limit,
            )

            typer.echo(
                f"\n=== NFS ALL === universe={universe}, endpoint={endpoint}, codes={len(codes)}, sink={resolved_sink}"
            )

            await run_ingest_many_with_progress(
                ucs=ucs,
                endpoints=endpoints,
                codes=codes,
                sleep_sec=resolved_sleep_sec,
                asof=run_asof,
                chunk_size=chunk_size,
                progress_every=1,
            )
        finally:
            await ucs.resources.aclose()

    asyncio.run(_run())
