from __future__ import annotations

import csv
import sys
from typing import Optional

import typer

from acs_cli.census_api import (
    fetch_acs_data,
    fetch_multi_year,
    format_value,
    get_api_key,
    write_csv,
)
from acs_cli.census_api.client import (
    CensusAPIError,
    InvalidAPIKeyError,
    MissingAPIKeyError,
    resolve_variables,
    save_api_key,
    DEFAULT_YEAR,
)
from acs_cli.topics import TOPICS

app = typer.Typer(help="ACS CLI — Query Census ACS 5-year data for Michigan counties (CSV output).")


def _get_key() -> str:
    try:
        return get_api_key()
    except MissingAPIKeyError as e:
        typer.echo(f"Error: {e}", err=True)
        raise typer.Exit(1)


def _handle_api_error(e: CensusAPIError | InvalidAPIKeyError) -> None:
    typer.echo(f"Error: {e}", err=True)
    raise typer.Exit(1)


@app.command()
def login(
    api_key: str = typer.Option(..., prompt="Census API key", help="Your Census API key"),
):
    """Save your Census API key. Get one at https://api.census.gov/data/key_signup.html"""
    path = save_api_key(api_key)
    typer.echo(f"API key saved to {path}", err=True)


@app.command()
def query(
    topics: Optional[list[str]] = typer.Argument(None, help="Topic names (e.g. population income) or 'all'"),
    year: int = typer.Option(DEFAULT_YEAR, "--year", "-y", help="Single ACS vintage year"),
    years: Optional[str] = typer.Option(None, "--years", help="Comma-separated years, e.g. '2019,2020,2023' (overrides --year)"),
    county: Optional[str] = typer.Option(None, "--county", "-c", help="Filter by county name substring"),
    sort: Optional[str] = typer.Option(None, "--sort", "-s", help="Sort descending by column label"),
    variable: Optional[list[str]] = typer.Option(None, "--variable", "-v", help="Raw Census variable codes"),
    output: Optional[str] = typer.Option(None, "--output", "-o", help="Write CSV to this file path instead of stdout"),
):
    """Query ACS data for Michigan counties. Output is CSV to stdout or a file via --output."""
    if not topics and not variable:
        typer.echo("Error: Provide topic names or use --variable / -v.", err=True)
        raise typer.Exit(1)
    api_key = _get_key()
    try:
        variables = resolve_variables(topics or [], variable)
    except ValueError as e:
        typer.echo(f"Error: {e}", err=True)
        raise typer.Exit(1)

    show_year = False
    try:
        if years:
            year_list = [int(y.strip()) for y in years.split(",")]
            rows = fetch_multi_year(variables, year_list, api_key)
            show_year = True
        else:
            rows = fetch_acs_data(variables, year, api_key)
    except (InvalidAPIKeyError, CensusAPIError) as e:
        _handle_api_error(e)

    if output:
        with open(output, "w", newline="") as f:
            writer = csv.writer(f)
            count = write_csv(rows, variables, writer, show_year=show_year, county_filter=county, sort_col=sort)
        if count:
            typer.echo(f"Wrote CSV to {output}", err=True)
        else:
            typer.echo("No matching rows found.", err=True)
    else:
        writer = csv.writer(sys.stdout)
        count = write_csv(rows, variables, writer, show_year=show_year, county_filter=county, sort_col=sort)
        if not count:
            typer.echo("No matching rows found.", err=True)


@app.command("topics")
def topics_cmd():
    """List available topics and their Census variables (CSV)."""
    writer = csv.writer(sys.stdout)
    writer.writerow(["Topic", "Variable Code", "Label", "Format"])
    for topic_name, vars_ in TOPICS.items():
        for v in vars_:
            writer.writerow([topic_name, v.code, v.label, v.format])


@app.command()
def info(
    county_name: str = typer.Argument(help="County name (or substring) to profile"),
    year: int = typer.Option(DEFAULT_YEAR, "--year", "-y", help="ACS vintage year"),
):
    """Full profile for a single county — all topics, CSV output."""
    api_key = _get_key()
    try:
        all_vars = resolve_variables(["all"], None)
        rows = fetch_acs_data(all_vars, year, api_key)
    except (InvalidAPIKeyError, CensusAPIError) as e:
        _handle_api_error(e)

    filt = county_name.lower()
    matches = [r for r in rows if filt in r.get("NAME", "").lower()]

    if not matches:
        typer.echo(f"No county matching '{county_name}' found.", err=True)
        raise typer.Exit(1)

    writer = csv.writer(sys.stdout)
    writer.writerow(["County", "Field", "Value"])
    from acs_cli.census_api.client import clean_county_name
    for row in matches:
        name = clean_county_name(row.get("NAME", ""))
        for v in all_vars:
            writer.writerow([name, v.label, format_value(row.get(v.code), v.format)])


if __name__ == "__main__":
    app()
