import json

import click
from geo.core.reader import read_dataset
from geo.core.writer import write_dataset
from geo.core.query import parse_bbox
from geo.formats import driver_for_path


@click.command("filter")
@click.argument("input_path", type=click.Path(exists=True))
@click.option("--bbox", default=None, help="Bounding box: west,south,east,north")
@click.option("--where", default=None, help="OGR SQL WHERE clause (e.g. \"pop > 1000\")")
@click.option("-o", "--output", "output_path", default=None,
              help="Output file. If omitted, GeoJSON is written to stdout.")
@click.option("--layer", default=None, help="Layer name (for multi-layer formats)")
@click.pass_context
def filter_cmd(ctx, input_path, bbox, where, output_path, layer):
    """Filter features by bounding box or attribute expression."""
    parsed_bbox = parse_bbox(bbox) if bbox else None

    # pyogrio supports 'bbox' and 'where' directly in read_dataframe
    # Note: parsed_bbox from core.query is a tuple (w, s, e, n) which pyogrio accepts
    
    # We use pyogrio.read_dataframe which loads into memory. 
    # For very large files, 'read_info' and 'read_bounds' could check first, 
    # but for this CLI tool, loading the filtered result is fine.
    
    try:
        gdf = read_dataset(input_path, layer=layer, bbox=parsed_bbox, where=where)
    except Exception as e:
        raise click.ClickException(f"Filter failed: {e}")

    if output_path:
        target_driver = driver_for_path(output_path)
        write_dataset(gdf, output_path, driver=target_driver)

        if not ctx.obj.get("quiet"):
            click.echo(f"Filtered {len(gdf)} features → {output_path}", err=True)
    else:
        # Write to stdout as GeoJSON
        # geopandas to_json() returns a string
        click.echo(gdf.to_json(indent=2 if not ctx.obj.get("json") else None))
