"""Phase 2: Project Setup"""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/02_setup.ipynb.

# %% auto 0
__all__ = ['launch_dev_servers', 'init_nbdev']

# %% ../nbs/02_setup.ipynb 3
import os
import subprocess
import sys
from pathlib import Path
import shutil
from .core import run_cmd, setup_dark_theme, find_free_port, hr
from .checks import check_prereqs

# %% ../nbs/02_setup.ipynb 5
def launch_dev_servers(project_path, args):
    """Launch Jupyter Lab and nbdev_preview in project venv
    
    TODO: Implement as separate `pj dev` command
    - Use project_path/.venv/bin/jupyter (not global)
    - Manage port allocation
    - Handle --no-preview, --no-lab, --code flags
    - Track PIDs for `pj kill`
    """
    pass

# %% ../nbs/02_setup.ipynb 7
def init_nbdev(args):
    """Initialize a new nbdev project with full configuration."""
    project_name = args.name
    
    # Phase 1: Checks
    user_info = check_prereqs()
    
    # Set up logging
    project_path = Path.cwd() / project_name

    if args.no_log:
        log_file = None
    else:
        log_file = Path(args.logfile) if args.logfile else Path.cwd() / "init.log"
        # Clear log file if it exists
        if log_file and log_file.exists():
            log_file.unlink()
        # Create empty log file
        if log_file:
            log_file.touch()

    
    # Phase 2: Setup
    print(hr * 60)
    print("PHASE 2: SETUP")
    
    # Build gh repo create command
    gh_cmd = ["gh", "repo", "create"]

    # If org specified, use ORG/PROJECT format
    if args.org:
        gh_cmd.append(f"{args.org}/{project_name}")
    else:
        gh_cmd.append(project_name)

    gh_cmd.append("--public" if args.public else "--private")
    gh_cmd.append("--clone")

    if args.description:
        gh_cmd.extend(["--description", args.description])

    #  1. Create GitHub repo
    print("📦 1. Creating GitHub repository")
    run_cmd(gh_cmd, log_file=log_file, verbose=args.verbose)
    
    #  2. Run nbdev_new
    print("📓 2. Setting up nbdev project")
    nbdev_cmd = [
        "nbdev_new",
        "--repo", project_name,
        "--user", user_info['gh_username'],
        "--author", args.author or user_info['git_user'],
        "--author_email", args.author_email or user_info['git_email'],
        "--description", args.description or f"A new nbdev project: {project_name}",
        "--jupyter_hooks", "True",
    ]
    
    if args.license:
        nbdev_cmd.extend(["--license", args.license])
    if args.min_python:
        nbdev_cmd.extend(["--min_python", args.min_python])
    
    run_cmd(nbdev_cmd, cwd=project_path, log_file=log_file, verbose=args.verbose)
    
    # 2b. Set up dark theme
    # print("🎨 2b. Setting up dark theme")
    setup_dark_theme(project_path, log_file=log_file, verbose=args.verbose)

    #  3. Create venv
    print("🐍 3. Creating virtual environment with uv")
    uv_venv_cmd = ["uv", "venv"]
    if args.python:
        uv_venv_cmd.extend(["--python", args.python])
    run_cmd(uv_venv_cmd, cwd=project_path, log_file=log_file, verbose=args.verbose)
    
    #  4. Install package
    print("📥 4. Installing package in editable mode")
    venv_python = project_path / ".venv" / "bin" / "python"
    run_cmd(
        ["uv", "pip", "install", "--python", str(venv_python), "-e", ".[dev]"],
        cwd=project_path, log_file=log_file, verbose=args.verbose
    )
    
    #  5. Install ipykernel
    print("🔧 5. Installing ipykernel")
    run_cmd(
        ["uv", "pip", "install", "--python", str(venv_python), "ipykernel"],
        cwd=project_path, log_file=log_file, verbose=args.verbose
    )
    
    #  6. Register Jupyter kernel
    print("📊 6. Registering Jupyter kernel")
    run_cmd(
        [str(venv_python), "-m", "ipykernel", "install", "--user", f"--name={project_name}"],
        log_file=log_file, verbose=args.verbose
    )
    
    #  7. Set up direnv
    print("🔄 7. Setting up direnv")
    envrc_path = project_path / ".envrc"
    envrc_path.write_text("source .venv/bin/activate\n")
    run_cmd(["direnv", "allow"], cwd=project_path, log_file=log_file, verbose=args.verbose)
    
    #  8. Update .gitignore
    print("✏️ 8. Updating .gitignore")
    gitignore_path = project_path / ".gitignore"
    entries_to_add = [".venv/", "init.log"]
    
    if gitignore_path.exists():
        content = gitignore_path.read_text()
        new_entries = [e for e in entries_to_add if e not in content]
        if new_entries:
            with gitignore_path.open("a") as f:
                f.write("\n" + "\n".join(new_entries) + "\n")
    else:
        gitignore_path.write_text("\n".join(entries_to_add) + "\n")
    
    # Phase 3: Sync
    print(hr * 60)
    print("PHASE 3: SYNC")
    
    #  9. Run nbdev_prepare
    print("🔧 9. Running nbdev_prepare")
    run_cmd(["nbdev_prepare"], cwd=project_path, check=False, log_file=log_file, verbose=args.verbose)
    
    # 10. Commit and push
    print("💾 10. Committing and pushing initial setup")
    run_cmd(["git", "add", "-A"], cwd=project_path, log_file=log_file, verbose=args.verbose)
    run_cmd(["git", "commit", "-m", "setup nbdev"], cwd=project_path, log_file=log_file, verbose=args.verbose)
    run_cmd(["git", "push", "-u", "origin", "HEAD"], cwd=project_path, log_file=log_file, verbose=args.verbose)

    # Move log file to project directory
    if log_file and log_file.exists():
        final_log_path = project_path / "init.log"
        log_file.rename(final_log_path)
        log_file = final_log_path

    # Success!
    print(hr * 60)
    print("✅ Project initialized successfully!")

    if log_file:
        print(f"\n📋 Full log: {log_file}")

    # Display project structure
    print(f"\n📁 Project structure:")
    if shutil.which("tree"):
        subprocess.run(["tree", "-a", "-I", ".git", "-L", "2"], cwd=project_path, check=False)
    else:
        subprocess.run(["ls", "-la"], cwd=project_path, check=False)

    # Handle quiet mode
    if args.quiet:
        args.no_preview = True
        args.no_lab = True

    # TODO: Replace this section with call to launch_dev_servers()
    # Launch nbdev_preview
    if not args.no_preview:
        print("\n🌐 Launching nbdev_preview")
        subprocess.Popen(
            ["nbdev_preview"],
            cwd=project_path,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            start_new_session=True
        )

    # Launch Jupyter Lab
    if not args.no_lab:
        port = find_free_port(64000)
        print(f"\n📓 Launching Jupyter Lab on port {port}")
        subprocess.Popen(
            ["jupyter-lab", f"--port={port}", "--NotebookApp.token=''", "--NotebookApp.password=''"],
            cwd=project_path,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            start_new_session=True
        )
        print(f"   Open: http://localhost:{port}")

    # Open VSCode
    if args.code:
        print("\n💻 Opening VSCode")
        subprocess.Popen(["code", "."], cwd=project_path)

    # Show background processes info
    if not args.no_preview or not args.no_lab:
        print(f"\n💡 Tip: Background processes running:")
        if not args.no_preview:
            print(f"   - nbdev_preview (kill with: pkill -f nbdev_preview)")
        if not args.no_lab:
            print(f"   - jupyter lab on port {port} (kill with: pkill -f 'jupyter.*{port}')")

    # Final message
    print(f"\n🎉 All done! Entering project directory...\n")

    # Change to project directory and exec into new shell
    os.chdir(project_path)
    os.execvp(os.environ.get("SHELL", "bash"), [os.environ.get("SHELL", "bash")])
