"""
Editor integration for coding problems.

Opens a temporary file in the user's preferred terminal editor so they can
write their solution.  The edited content is read back and returned as a
string.

Editor preference order:
  1. SKILARK_EDITOR env var  (Skilark-specific override)
  2. VISUAL env var          (Unix standard for full-screen editors)
  3. EDITOR env var          (Unix standard for line editors)
  4. nano                    (if available on PATH)
  5. vi                      (always present on POSIX systems)
"""

from __future__ import annotations

import os
import shlex
import shutil
import subprocess
import tempfile
from pathlib import Path


# Map language slugs to file extensions for syntax highlighting in editors.
_LANGUAGE_EXTENSIONS: dict[str, str] = {
    "python": ".py",
    "java": ".java",
    "javascript": ".js",
    "typescript": ".ts",
    "go": ".go",
    "rust": ".rs",
    "cpp": ".cpp",
    "c": ".c",
}


def get_editor() -> str:
    """Return the name or path of the editor to use.

    Checks environment variables in priority order, then falls back to
    system-installed editors.

    Returns:
        Editor command string suitable for use as the first element of a
        subprocess command list (e.g. 'vim', 'code', 'nano').
    """
    for env_var in ("SKILARK_EDITOR", "VISUAL", "EDITOR"):
        val = os.environ.get(env_var)
        if val:
            return val

    # Fallback: prefer nano (friendlier for beginners) then vi.
    if shutil.which("nano"):
        return "nano"

    return "vi"


def open_in_editor(starter_code: str, language: str) -> str:
    """Open *starter_code* in the user's preferred editor and return the result.

    Writes *starter_code* to a temporary file with the correct extension for
    *language*, launches the editor process, waits for it to exit, reads the
    (possibly modified) file content, then deletes the temp file.

    Args:
        starter_code: Initial content to pre-populate in the editor.
        language:     Language slug (e.g. 'python', 'java').  Determines the
                      file extension, which enables syntax highlighting in
                      editors that support it.

    Returns:
        The file content after the editor exits.  This may be the original
        starter code (if the user made no changes) or the user's solution.
    """
    ext = _LANGUAGE_EXTENSIONS.get(language.lower(), ".txt")
    editor = get_editor()

    tmp_path: str | None = None
    try:
        fd, tmp_path = tempfile.mkstemp(suffix=ext, prefix="skilark_")
        try:
            os.write(fd, starter_code.encode())
        finally:
            os.close(fd)

        subprocess.run([*shlex.split(editor), tmp_path], check=False)

        return Path(tmp_path).read_text()

    finally:
        if tmp_path and os.path.exists(tmp_path):
            os.unlink(tmp_path)
