"""
venvy.utils.shell
~~~~~~~~~~~~~~~~~
Shell activation helpers.

Because shells cannot be subprocesses that change the PARENT shell's environment,
venvy generates shell function definitions that users add to their shell profile.
When users run `venvy +` or `venvy -`, the shell function is called instead,
which can `source` the activate script in the CURRENT shell session.
"""

from __future__ import annotations

import platform
from pathlib import Path

IS_WINDOWS = platform.system() == "Windows"


BASH_ZSH_INIT = """\
# venvy shell integration — added by `venvy init-shell`
# Source this in your ~/.bashrc, ~/.zshrc, or ~/.bash_profile

venvy() {{
    if [ "$1" = "+" ]; then
        # Activate: find venv from .venvy.json
        local cfg
        cfg=$(python3 -c "
import json, sys
from pathlib import Path
cur = Path.cwd()
for d in [cur, *cur.parents]:
    cfg = d / '.venvy.json'
    if cfg.exists():
        data = json.loads(cfg.read_text())
        venv = d / data.get('venv_name', '.venv')
        print(str(venv / 'bin' / 'activate'))
        sys.exit(0)
# fallback: look for common venv dirs
for name in ('.venv', 'venv', 'env', '.env'):
    p = cur / name / 'bin' / 'activate'
    if p.exists():
        print(str(p))
        sys.exit(0)
print('__not_found__')
" 2>/dev/null)
        if [ "$cfg" = "__not_found__" ] || [ -z "$cfg" ]; then
            echo "[venvy] No virtual environment found in this project."
            return 1
        fi
        source "$cfg"
        echo "[venvy] Activated: $VIRTUAL_ENV"
    elif [ "$1" = "-" ]; then
        # Deactivate
        if [ -n "$VIRTUAL_ENV" ]; then
            deactivate
            echo "[venvy] Deactivated virtual environment."
        else
            echo "[venvy] No active virtual environment."
        fi
    else
        # Pass all other commands to the real venvy CLI
        command venvy "$@"
    fi
}}
"""

FISH_INIT = """\
# venvy shell integration — added by `venvy init-shell`
# Source this in your ~/.config/fish/config.fish

function venvy
    if test "$argv[1]" = "+"
        # Find and activate venv
        set cfg (python3 -c "
import json, sys
from pathlib import Path
cur = Path.cwd()
for d in [cur, *cur.parents]:
    cfg = d / '.venvy.json'
    if cfg.exists():
        data = json.loads(cfg.read_text())
        venv = d / data.get('venv_name', '.venv')
        print(str(venv / 'bin' / 'activate.fish'))
        sys.exit(0)
for name in ('.venv', 'venv', 'env', '.env'):
    p = cur / name / 'bin' / 'activate.fish'
    if p.exists():
        print(str(p))
        sys.exit(0)
print('__not_found__')
" 2>/dev/null)
        if test "$cfg" = "__not_found__" -o -z "$cfg"
            echo "[venvy] No virtual environment found."
            return 1
        end
        source "$cfg"
        echo "[venvy] Activated: $VIRTUAL_ENV"
    else if test "$argv[1]" = "-"
        if set -q VIRTUAL_ENV
            deactivate
            echo "[venvy] Deactivated."
        else
            echo "[venvy] No active virtual environment."
        end
    else
        command venvy $argv
    end
end
"""

POWERSHELL_INIT = r"""
# venvy shell integration — added by `venvy init-shell`
# Add to your $PROFILE (run `notepad $PROFILE` to edit)

function venvy {
    if ($args[0] -eq '+') {
        # Find venv
        $cur = Get-Location
        $cfg = $null
        $dir = $cur
        while ($dir -ne $null) {
            $cfgPath = Join-Path $dir '.venvy.json'
            if (Test-Path $cfgPath) {
                $data = Get-Content $cfgPath | ConvertFrom-Json
                $venvName = if ($data.venv_name) { $data.venv_name } else { '.venv' }
                $cfg = Join-Path $dir "$venvName\Scripts\Activate.ps1"
                break
            }
            $parent = Split-Path $dir -Parent
            if ($parent -eq $dir) { break }
            $dir = $parent
        }
        if (-not $cfg -or -not (Test-Path $cfg)) {
            # Fallback: search common venv names
            foreach ($name in @('.venv','venv','env','.env')) {
                $p = Join-Path $cur "$name\Scripts\Activate.ps1"
                if (Test-Path $p) { $cfg = $p; break }
            }
        }
        if ($cfg -and (Test-Path $cfg)) {
            & $cfg
            Write-Host "[venvy] Activated: $env:VIRTUAL_ENV" -ForegroundColor Green
        } else {
            Write-Host "[venvy] No virtual environment found." -ForegroundColor Red
        }
    } elseif ($args[0] -eq '-') {
        if ($env:VIRTUAL_ENV) {
            deactivate
            Write-Host "[venvy] Deactivated." -ForegroundColor Yellow
        } else {
            Write-Host "[venvy] No active virtual environment." -ForegroundColor Yellow
        }
    } else {
        & venvy.exe $args
    }
}
"""


def get_shell_init_script(shell: str = "bash") -> str:
    """Return the shell integration snippet for the requested shell."""
    shell = shell.lower()
    if shell in ("bash", "zsh", "sh"):
        return BASH_ZSH_INIT
    elif shell == "fish":
        return FISH_INIT
    elif shell in ("powershell", "pwsh"):
        return POWERSHELL_INIT
    else:
        return BASH_ZSH_INIT


def detect_shell() -> str:
    """Best-effort detection of the user's current shell."""
    import os
    shell_env = os.environ.get("SHELL", "")
    if "zsh" in shell_env:
        return "zsh"
    elif "fish" in shell_env:
        return "fish"
    elif "bash" in shell_env:
        return "bash"
    elif IS_WINDOWS:
        return "powershell"
    return "bash"


def get_profile_path(shell: str) -> str:
    """Return suggested shell profile path."""
    mapping = {
        "bash": "~/.bashrc  (or ~/.bash_profile on macOS)",
        "zsh": "~/.zshrc",
        "fish": "~/.config/fish/config.fish",
        "powershell": "$PROFILE  (run: notepad $PROFILE)",
    }
    return mapping.get(shell, "~/.bashrc")
