import typer
from typing import Optional
from pathlib import Path
from rich.console import Console
from sibi_flux.init.core import initialize_project

app = typer.Typer(help="Sibi Flux CLI")
console = Console()


@app.callback()
def callback():
    """
    Sibi Flux CLI
    """


@app.command()
def init(
    project_name: Optional[str] = typer.Argument(None, help="Name of the project to create"),
    lib: bool = typer.Option(
        False, "--lib", help="Initialize as a library project (passed to uv init)"
    ),
    app: bool = typer.Option(
        False, "--app", help="Initialize as an application project (passed to uv init)"
    ),
    osmnx: bool = typer.Option(
        False, "--osmnx", help="Include OSMnx (geospatial) support"
    ),
):
    """
    Initialize a new Sibi Flux project.

    Creates a new directory <project_name>, initializes it with 'uv',
    and adds 'sibi-flux' as a dependency.
    """
    if project_name is None:
        from sibi_flux.init.core import initialize_project_interactive
        project_name, lib, app, osmnx = initialize_project_interactive()
    
    initialize_project(project_name, lib, app, use_osmnx=osmnx)


@app.command()
def create_app(
    name: str = typer.Argument(..., help="Name of the application to create"),
):
    """
    Create a new application within an existing Sibi Flux project.
    
    Generates standard directory structure in `<project_root>/<name>`.
    """
    from sibi_flux.init.app import init_app
    init_app(name)




# --- Readers Workflow Group ---
readers_app = typer.Typer(help="Sibi-Flux Reader Management")


@readers_app.command()
def prepare(
    domain: Optional[str] = typer.Argument(None, help="Domain name for the readers (e.g., 'logistics')"),
    layout_name: Optional[str] = typer.Option(None, "--layout", "-l", help="S3 layout name to use (from storage.yaml)"),
    depot_name: Optional[str] = typer.Option(None, "--depot", "-d", help="Specific depot to filter readers from"),
    force: bool = typer.Option(False, "--force", "-f", help="Force overwrite of existing configuration"),
):
    """
    Phase 1: Discovery. Scan global storage configuration and propose reader blueprints in `blueprints/readers/<domain>.yaml`.
    """
    from sibi_flux.init.reader_proposer import propose_readers
    
    if domain:
        propose_readers(domain, layout_name=layout_name, depot_name=depot_name, force=force)
    else:
        # Auto-discover domains from storage.yaml
        from sibi_flux.core import ProjectService
        import yaml
        
        project_root = ProjectService.detect_project_root()
        storage_path = project_root / "conf" / "storage.yaml"
        
        if not storage_path.exists():
            console.print("[yellow]Warning: conf/storage.yaml not found. Cannot auto-discover domains.[/yellow]")
            return
            
        with open(storage_path, "r") as f:
            data = yaml.safe_load(f) or {}
            filesystems = data.get("filesystems", [])
            domains = [fs.get("id") for fs in filesystems if fs.get("id")]
            
        if not domains:
            console.print("[yellow]No storage domains found in storage.yaml.[/yellow]")
            return
            
        console.print(f"[blue]Auto-discovered {len(domains)} domains: {', '.join(domains)}[/blue]")
        for d in domains:
            propose_readers(d, layout_name=layout_name, depot_name=depot_name, force=force)


@readers_app.command()
def apply(
    domain: Optional[str] = typer.Argument(None, help="Domain name for the readers"),
    force: bool = typer.Option(False, "--force", "-f", help="Force overwrite of existing files"),
):
    """
    Phase 2: Implementation. Generate Reader subclasses in `_gen/assets/readers/<domain>.py` from blueprints.
    """
    from sibi_flux.init.reader_extender import create_readers
    
    if domain:
        create_readers(domain, force=force)
    else:
        # Auto-discover from blueprints
        from sibi_flux.core import ProjectService
        project_root = ProjectService.detect_project_root()
        readers_dir = project_root / "blueprints" / "readers"
        gen_dir = project_root / "_gen" / "assets" / "readers"
        
        blueprints = list(readers_dir.glob("*.yaml")) if readers_dir.exists() else []
        blueprint_domains = {f.stem for f in blueprints}
        
        # Also discover existing generated assets for cleanup
        gen_assets = list(gen_dir.glob("*.py")) if gen_dir.exists() else []
        gen_domains = {f.stem for f in gen_assets if f.stem != "__init__"}
        
        # Total set of domains to process (apply or cleanup)
        all_domains = blueprint_domains | gen_domains
        
        if not all_domains:
            console.print("[yellow]No Reader blueprints or generated assets found.[/yellow]")
            return
            
        console.print(f"[blue]Applying {len(blueprint_domains)} blueprints and checking {len(gen_domains)} assets...[/blue]")
        for d in sorted(all_domains):
            create_readers(d, force=force)


@readers_app.command()
def workflow(
    domain: Optional[str] = typer.Argument(None, help="Domain name for the readers"),
    layout_name: Optional[str] = typer.Option(None, "--layout", "-l", help="S3 layout name to use"),
    depot_name: Optional[str] = typer.Option(None, "--depot", "-d", help="Specific depot to filter"),
    force: bool = typer.Option(False, "--force", "-f", help="Force overwrite"),
):
    """
    Executes the full Reader workflow: Prepare (Discovery) -> Apply (Implementation).
    """
    prepare(domain, layout_name=layout_name, depot_name=depot_name, force=force)
    apply(domain, force=force)


@app.command()
def env(
    project_path: Path = typer.Argument(Path("."), help="Project root directory"),
    env_file: Optional[Path] = typer.Option(
        None, "--env-file", "-e", help="Path to environment file (defaults to .env)"
    ),
    cleanup: bool = typer.Option(
        False, "--cleanup", help="Remove existing configuration files"
    ),
    production: bool = typer.Option(
        False,
        "--production",
        "-p",
        help="Generate production skeleton (no hardcoded values)",
    ),
    settings: bool = typer.Option(True, "--settings/--no-settings", help="Run settings.py generation"),
    creds: bool = typer.Option(True, "--creds/--no-creds", help="Run credentials generation"),
    discover: bool = typer.Option(True, "--discover/--no-discover", help="Run host discovery"),
    infra: bool = typer.Option(True, "--infra/--no-infra", help="Run infrastructure code generation"),
):
    """
    Initialize configuration files (settings.py, credentials) based on .env
    """
    from sibi_flux.init.env import init_env

    init_env(
        project_path, 
        env_file, 
        cleanup=cleanup, 
        production_mode=production,
        run_settings=settings,
        run_creds=creds,
        run_discover=discover,
        run_infra=infra
    )


# Mount Sub-commands
from sibi_flux.datacube.cli import app as dc_app
from sibi_flux.init.config_cli import app as config_app

app.add_typer(dc_app, name="dc", help="Datacube generation and management commands")
app.add_typer(readers_app, name="readers", help="Reader management and code generation")
app.add_typer(config_app, name="config", help="Configuration management commands")


if __name__ == "__main__":
    app()
