import subprocess
import os
import sys
from pathlib import Path
from rich.console import Console
import typer

console = Console()


def initialize_project(
    project_name: str,
    lib: bool = False,
    app: bool = False,
) -> None:
    """
    Initialize a new Sibi Flux project with the standard directory structure and configuration.

    Args:
        project_name: The name of the project directory to create.
        lib: If True, initialize as a library project via `uv init --lib`.
        app: If True, initialize as an application project via `uv init --app`.
             Note: If `lib` is False, the default behavior will be to include `--app`
             unless `app` is explicitly False. (Aligned with CLI defaults).
    """
    project_path = Path(os.getcwd()) / project_name

    # Handle "." case
    is_current_dir = project_name == "."
    if is_current_dir:
        project_path = Path(os.getcwd())

    if project_path.exists() and not is_current_dir:
        console.print(f"[red]Error: Directory '{project_name}' already exists.[/red]")
        raise typer.Exit(code=1)

    display_name = project_path.name if is_current_dir else project_name
    console.print(
        f"[bold blue]Initializing Sibi Flux project: {display_name}[/bold blue]"
    )

    # 1. Create Directory
    try:
        # Run `uv init`
        # if project_name match ".", pass it directly.
        cmd = ["uv", "init"]
        if not is_current_dir:
            cmd.append(project_name)

        if lib:
            cmd.append("--lib")
        else:
            cmd.append("--app")

        console.print(f"Running: {' '.join(cmd)}")
        subprocess.check_call(cmd)

        # 2. Add sibi-flux dependency
        console.print(f"Adding sibi-flux dependency...")
        try:
            from importlib.metadata import version

            ver = version("sibi-flux")
            pkg_spec = f"sibi-flux>={ver}"
        except Exception:
            pkg_spec = "sibi-flux@latest"

        subprocess.check_call(["uv", "add", pkg_spec], cwd=project_path)

        # 2b. Add dev dependencies
        dev_deps = [
            "black",
            "notebook",
            "pytest",
            "ruff",
            "httpx",
            "poethepoet",
            "PyYAML",
            "uvicorn",
        ]
        console.print(f"Adding dev dependencies: {', '.join(dev_deps)}...")
        subprocess.check_call(["uv", "add", "--dev"] + dev_deps, cwd=project_path)

        # 3. Create Scaffolding Folders (conf, dataobjects, generators)
        (project_path / "conf").mkdir(exist_ok=True)
        (project_path / "dataobjects").mkdir(exist_ok=True)
        (project_path / "generators" / "datacubes").mkdir(parents=True, exist_ok=True)

        # Add basic .gitkeep
        (project_path / "conf" / ".gitkeep").touch()
        (project_path / "dataobjects" / ".gitkeep").touch()
        (project_path / "generators" / ".gitkeep").touch()
        (project_path / "dataobjects" / "globals").mkdir(exist_ok=True)
        (project_path / "dataobjects" / "globals" / ".gitkeep").touch()
        # (project_path / "generators" / "datacubes" / ".gitkeep").touch() # Not needed if we write params

        # 4. Write YAML templates to conf/
        try:
            from importlib import resources as importlib_resources
            pass
        except ImportError:
            import importlib_resources  # type: ignore

        # A. discovery_params.yaml
        try:
            ref = importlib_resources.files("sibi_flux.init.templates").joinpath(
                "discovery_params.yaml"
            )
            template_content = ref.read_text()
        except AttributeError:
            template_content = importlib_resources.read_text(
                "sibi_flux.init.templates", "discovery_params.yaml"
            )

        template_content = template_content.replace(".env.linux", ".env.local")
        (project_path / "conf" / "discovery_params.yaml").write_text(template_content)

        # B. property_template.yaml
        try:
            ref_prop = importlib_resources.files("sibi_flux.init.templates").joinpath(
                "property_template.yaml"
            )
            prop_content = ref_prop.read_text()
        except AttributeError:
            prop_content = importlib_resources.read_text(
                "sibi_flux.init.templates", "property_template.yaml"
            )

        (project_path / "conf" / "property_template.yaml").write_text(prop_content)

        # C. Write gen_dc.py to generators/datacubes/
        try:
            ref_gen = importlib_resources.files("sibi_flux.init.templates").joinpath(
                "gen_dc.py"
            )
            gen_content = ref_gen.read_text()
        except AttributeError:
            gen_content = importlib_resources.read_text(
                "sibi_flux.init.templates", "gen_dc.py"
            )

        (project_path / "generators" / "datacubes" / "gen_dc.py").write_text(
            gen_content
        )

        # 5. Create .env.local
        (project_path / ".env.local").touch()

        # 6. Create/Update .gitignore
        gitignore_path = project_path / ".gitignore"
        gitignore_content = ""
        if gitignore_path.exists():
            gitignore_content = gitignore_path.read_text()

        # Ensure .env is ignored
        if ".env" not in gitignore_content:
            with open(gitignore_path, "a") as f:
                if gitignore_content and not gitignore_content.endswith("\n"):
                    f.write("\n")
                f.write("\n# Environment variables\n.env\n.env.local\n.env.*\n")

        if not gitignore_path.exists():
            gitignore_path.write_text(
                "# Sibi Flux\n.env\n.env.local\n.env.*\n__pycache__/\n*.pyc\n.DS_Store\n"
            )

        # 7. Configure poe tasks in pyproject.toml
        pyproject_path = project_path / "pyproject.toml"
        if pyproject_path.exists():
            with open(pyproject_path, "a") as f:
                f.write("\n\n[tool.poe.tasks]\n")
                f.write('dc-sync = "python generators/datacubes/gen_dc.py sync"\n')
                f.write('dc-init = "python generators/datacubes/gen_dc.py init"\n')
                f.write(
                    'dc-discover = "python generators/datacubes/gen_dc.py discover"\n'
                )
                f.write('dc-scan = "python generators/datacubes/gen_dc.py scan"\n')
                f.write('dc-match = "python generators/datacubes/gen_dc.py match"\n')
                f.write('dc-map = "python generators/datacubes/gen_dc.py map"\n')

        console.print(
            f"[bold green]Successfully initialized {project_name}![/bold green]"
        )
        console.print(
            f"Created directories: conf/, dataobjects/, generators/datacubes/"
        )
        console.print(
            f"Created files: .env.local, .gitignore, conf/[discovery_params.yaml, property_template.yaml], generators/datacubes/gen_dc.py"
        )
        console.print(f"cd {project_name}")

    except subprocess.CalledProcessError as e:
        console.print(f"[red]Command failed with exit code {e.returncode}[/red]")
        raise typer.Exit(code=e.returncode)
    except FileNotFoundError:
        console.print(
            "[red]Error: 'uv' command not found. Please ensure uv is installed and in your PATH.[/red]"
        )
        raise typer.Exit(code=1)
