"""
Initialize an rixpress project by creating gen-env.R and gen-pipeline.R.

This is a direct translation of the R function `rxp_init` into Python.

Behavior:

- Creates (overwrites) two files in the project directory:
  - gen-env.R
  - gen-pipeline.R

- Asks the user for confirmation before making changes, unless skip_prompt=True.
- Creates the project directory if it does not exist.
- If running non-interactively (e.g. CI), skips Git initialization and returns True.
- If the user agrees to initialise git, attempts to run `git init` in the project directory.
  If `git` is not available it prints an informative message.
- Returns True on successful initialization, False if the user cancels before making changes.
"""
from __future__ import annotations

import shutil
import subprocess
import sys
from pathlib import Path
from typing import Optional


def _is_interactive() -> bool:
    # Determine if the session is interactive (rough equivalent to R's interactive()).
    # Using stdin.isatty() is the usual heuristic.
    try:
        return sys.stdin.isatty()
    except Exception:
        return False


def _confirm(question: str, skip_prompt: bool) -> bool:
    """
    Ask the user a yes/no question. If skip_prompt is True, return True.
    Non-interactive sessions default to True/False behavior consistent with skip_prompt.
    """
    if skip_prompt:
        return True
    if not _is_interactive():
        # Non-interactive -> behave as R implementation: treat as non-interactive and
        # don't prompt (the caller handles skipping git init later). Here, return False
        # to indicate that interactive confirmation did not occur.
        # However the R version uses an initial confirmation that cancels the whole operation;
        # for parity we treat non-interactive as "cannot prompt", so default to False.
        return False
    try:
        ans = input(f"{question} [y/n]: ").strip().lower()
        if not ans:
            return False
        return ans[0] == "y"
    except Exception:
        return False


def rxp_init(project_path: str = ".", skip_prompt: bool = False) -> bool:
    """
    rxp_init

    Initialize rixpress project files in project_path. This will generate
    two R scripts: `gen-env.R`, which when executed using the rix R package
    will generate a `default.nix`, which defines the pipeline's execution
    environment, and `gen-pipeline.R`, which is where the pipeline is defined.
    These R scripts are the same as those generated by rixpress, the R version
    of this package.

    Returns:
      True if initialization completed (or was skipped due to non-interactive but files present),
      False if cancelled by the user.
    """
    # Initial confirmation before any action
    if not _confirm(f"Initialize project at '{project_path}'?", skip_prompt=skip_prompt):
        print("Operation cancelled by user. No files or directories were created.")
        return False

    proj = Path(project_path)
    # Ensure project_path exists, create it if it doesn't
    if not proj.exists():
        proj.mkdir(parents=True, exist_ok=True)

    env_file = proj / "gen-env.R"
    pipeline_file = proj / "gen-pipeline.R"

    gen_env_lines = [
        "# This script defines the default environment the pipeline runs in.",
        "# Add the required packages to execute the code necessary for each derivation.",
        "# If you want to create visual representations of the pipeline, consider adding",
        "# `{visNetwork}` and `{ggdag}` to the list of R packages.",
        "library(rix)",
        "",
        "# Define execution environment",
        "rix(",
        "  date = NULL,",
        "  r_pkgs = NULL,",
        "  py_conf = NULL,",
        "  git_pkgs = list(",
        "    \"package_name\" = \"rixpress\",",
        "    \"repo_url\" = \"https://github.com/b-rodrigues/rixpress\",",
        "    \"commit\" = \"HEAD\",",
        "  ),",
        "  ide = \"none\",",
        "  project_path = \".\"",
        ")",
    ]

    gen_pipeline_lines = [
        "library(rixpress)",
        "library(igraph)",
        "",
        "list(",
        "  rxp_r_file(",
        "    name = NULL,",
        "    path = NULL,",
        "    read_function = \"lambda x: polars.read_csv(x, separator='|')\"",
        "  ),",
        "  rxp_r(",
        "    name = NULL,",
        "    expr = NULL",
        "  )",
        ") |>",
        "  rxp_populate(build = FALSE)",
    ]

    # Write files (overwrite if present)
    env_file.write_text("\n".join(gen_env_lines) + "\n", encoding="utf-8")
    print(f"File {env_file} has been written.")
    pipeline_file.write_text("\n".join(gen_pipeline_lines) + "\n", encoding="utf-8")
    print(f"File {pipeline_file} has been written.")

    # Skip Git initialization when on non-interactive sessions (CRAN/CI/test equivalent)
    if not _is_interactive():
        print(
            "Skipping Git initialization (non-interactive session, CRAN, CI, or test environment detected)."
        )
        return True

    # Ask whether to initialise git
    if _confirm("Would you like to initialise a Git repository here?", skip_prompt=skip_prompt):
        git_bin = shutil.which("git")
        if git_bin is None:
            print(
                "Git not found on PATH. Please install git and run 'git init' manually, "
                "or initialise the repository using your preferred tool."
            )
        else:
            try:
                subprocess.run([git_bin, "init"], cwd=str(proj), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                print("Git repository initialised.")
            except subprocess.CalledProcessError as e:
                print("Failed to initialise git repository. You can run 'git init' manually.")
    else:
        print("Skipping Git initialization.")

    return True
