"""Command-line interface for schemai."""

import sys
from pathlib import Path
from typing import Optional

import click

from schemai.inferencer import SchemaInferencer


@click.group()
@click.version_option(version="0.1.0")
def cli():
    """Schemai - Infer Pydantic schemas from JSON and CSV files."""
    pass


@cli.command()
@click.argument("file", type=click.Path(exists=True))
@click.option(
    "-n",
    "--name",
    default="GeneratedModel",
    help="Name for the generated model class.",
)
@click.option(
    "-o",
    "--output",
    type=click.Path(),
    help="Output file path (if not provided, prints to stdout).",
)
@click.option(
    "-f",
    "--format",
    type=click.Choice(["model", "code"]),
    default="code",
    help="Output format: 'model' for full model definition, 'code' for just the class.",
)
@click.option(
    "--strict",
    is_flag=True,
    help="Enable strict type checking (no type coercion).",
)
def infer(file: str, name: str, output: Optional[str], format: str, strict: bool):
    """
    Infer a Pydantic schema from a JSON or CSV file.
    
    FILE: Path to JSON or CSV file
    """
    try:
        path = Path(file)
        inferencer = SchemaInferencer(strict=strict)

        # Determine file type and infer schema
        if path.suffix.lower() == ".json":
            model = inferencer.infer_from_json(path, model_name=name)
        elif path.suffix.lower() == ".csv":
            model = inferencer.infer_from_csv(path, model_name=name)
        else:
            click.echo(f"Error: Unsupported file type: {path.suffix}", err=True)
            sys.exit(1)

        # Generate output
        if format == "code":
            result = inferencer.to_code(model, class_name=name)
        else:
            # Show model schema
            result = model.model_json_schema()
            import json
            result = json.dumps(result, indent=2)

        # Output result
        if output:
            output_path = Path(output)
            output_path.write_text(result)
            click.echo(f"✓ Schema written to {output_path}")
        else:
            click.echo(result)

    except FileNotFoundError as e:
        click.echo(f"Error: {e}", err=True)
        sys.exit(1)
    except ValueError as e:
        click.echo(f"Error: {e}", err=True)
        sys.exit(1)
    except Exception as e:
        click.echo(f"Error: {e}", err=True)
        sys.exit(1)


@cli.command()
@click.argument("files", nargs=-1, type=click.Path(exists=True), required=True)
@click.option(
    "-o",
    "--output",
    type=click.Path(),
    help="Output directory for generated models.",
)
def batch(files, output: Optional[str]):
    """
    Infer schemas from multiple files.
    
    FILES: Paths to JSON or CSV files
    """
    if not files:
        click.echo("Error: At least one file is required.", err=True)
        sys.exit(1)

    output_dir = Path(output) if output else Path.cwd()
    output_dir.mkdir(parents=True, exist_ok=True)

    inferencer = SchemaInferencer()
    
    for file_path in files:
        try:
            path = Path(file_path)
            model_name = path.stem.title().replace("_", "").replace("-", "")

            if path.suffix.lower() == ".json":
                model = inferencer.infer_from_json(path, model_name=model_name)
            elif path.suffix.lower() == ".csv":
                model = inferencer.infer_from_csv(path, model_name=model_name)
            else:
                click.echo(f"⚠ Skipping unsupported file type: {path.suffix}")
                continue

            code = inferencer.to_code(model, class_name=model_name)
            output_file = output_dir / f"{path.stem}_schema.py"
            output_file.write_text(code)
            
            click.echo(f"✓ {path.name} → {output_file.name}")

        except Exception as e:
            click.echo(f"✗ Error processing {file_path}: {e}", err=True)


@cli.command()
@click.argument("file", type=click.Path(exists=True))
@click.option(
    "--sample-rows",
    type=int,
    help="Number of rows to sample from CSV.",
)
def info(file: str, sample_rows: Optional[int]):
    """
    Display information about a file's inferred schema.
    
    FILE: Path to JSON or CSV file
    """
    try:
        path = Path(file)
        inferencer = SchemaInferencer()

        if path.suffix.lower() == ".json":
            model = inferencer.infer_from_json(path)
        elif path.suffix.lower() == ".csv":
            model = inferencer.infer_from_csv(path, sample_rows=sample_rows)
        else:
            click.echo(f"Error: Unsupported file type: {path.suffix}", err=True)
            sys.exit(1)

        click.echo(f"\nFile: {path.name}")
        click.echo(f"Type: {path.suffix[1:].upper()}")
        click.echo(f"\nInferred Fields:")
        click.echo("-" * 50)

        for field_name, field_info in model.model_fields.items():
            annotation = field_info.annotation
            nullable = "nullable" in str(annotation).lower()
            click.echo(f"  {field_name}: {annotation}")

    except Exception as e:
        click.echo(f"Error: {e}", err=True)
        sys.exit(1)


def main():
    """Main entry point for CLI."""
    cli()


if __name__ == "__main__":
    main()
