"""
Fix suggestion UI and command execution for goCLI.

Displays the inline suggestion prompt and, if confirmed, executes
the fix command. Cross-platform (Windows, macOS, Linux).
"""

from __future__ import annotations

import subprocess
import sys
from typing import Optional

from .config import CORAL, OFF_WHITE, MUTED, RESET, LABEL, IS_WINDOWS


def _write(text: str) -> None:
    """Write directly to stderr."""
    sys.stderr.write(text)
    sys.stderr.flush()


def present_suggestion(
    description: str,
    fix_command: str,
) -> bool:
    """Show the three-line suggestion UI and return ``True`` if accepted.

    Layout::

        goCLI  detected an error
               fix  <command>
               run? [Y/n]
    """
    _write("\n")
    _write(f"  {LABEL}  {OFF_WHITE}detected an error{RESET}\n")
    _write(f"         {MUTED}fix  {CORAL}{fix_command}{RESET}\n")
    _write(f"         {MUTED}run? {OFF_WHITE}[Y/n]{RESET} ")

    try:
        answer = input().strip().lower()
    except (EOFError, KeyboardInterrupt):
        _write("\n")
        return False

    return answer in ("", "y", "yes")


def execute_fix(fix_command: str) -> Optional[int]:
    """Run *fix_command* in a sub-shell and return the exit code.

    Uses cmd.exe on Windows, sh on Unix.
    Returns ``None`` if the command could not be started.
    """
    _write(f"\n  {LABEL}  {MUTED}running fix...{RESET}\n\n")

    if IS_WINDOWS:
        args = ["cmd.exe", "/c", fix_command]
    else:
        args = ["sh", "-c", fix_command]

    try:
        result = subprocess.run(
            args,
            stdin=sys.stdin,
            stdout=sys.stdout,
            stderr=sys.stderr,
        )
        returncode = result.returncode
    except OSError:
        _write(f"  {LABEL}  {CORAL}could not execute command{RESET}\n")
        return None

    if returncode == 0:
        _write(f"\n  {LABEL}  {OFF_WHITE}fix applied{RESET}\n\n")
    else:
        _write(
            f"\n  {LABEL}  {CORAL}command exited with code "
            f"{returncode}{RESET}\n\n"
        )

    return returncode
