"""Environment configuration handler mixin for IeumApp."""
# ruff: noqa: BLE001, PLR0912, PLR2004, S110

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING, ClassVar

from ieum.i18n import t

if TYPE_CHECKING:
    pass


class EnvHandlerMixin:
    """Environment variable management methods for IeumApp."""

    # Supported environment variables for /env command
    _ENV_KEYS: ClassVar[dict[str, str]] = {
        # LLM Providers
        "OPENAI_API_KEY": "OpenAI API 키",
        "ANTHROPIC_API_KEY": "Anthropic (Claude) API 키",
        "GOOGLE_API_KEY": "Google AI API 키",
        "GROQ_API_KEY": "Groq API 키",
        "MISTRAL_API_KEY": "Mistral API 키",
        "COHERE_API_KEY": "Cohere API 키",
        "NVIDIA_API_KEY": "NVIDIA NIM API 키",
        "OPENROUTER_API_KEY": "OpenRouter API 키",
        "DEEPSEEK_API_KEY": "DeepSeek API 키",
        "UPSTAGE_API_KEY": "Upstage API 키",
        "DASHSCOPE_API_KEY": "Qwen/Tongyi API 키",
        "ZHIPUAI_API_KEY": "ZhipuAI API 키",
        # Tools
        "TAVILY_API_KEY": "Tavily 검색 API 키",
        # Observability
        "LANGFUSE_PUBLIC_KEY": "Langfuse Public 키",
        "LANGFUSE_SECRET_KEY": "Langfuse Secret 키",
        "LANGFUSE_HOST": "Langfuse 호스트 URL",
    }

    async def _cmd_env(self, command: str) -> None:
        """Handle /env command for environment variable management.

        Subcommands:
            /env              - Show all environment variables status
            /env list         - Same as /env
            /env set KEY val  - Set environment variable
            /env unset KEY    - Remove environment variable
        """
        from ieum.widgets.messages import SystemMessage

        parts = command.strip().split(maxsplit=2)

        if len(parts) == 1 or (len(parts) == 2 and parts[1].lower() == "list"):
            # /env or /env list - show status
            await self._env_list()
        elif len(parts) >= 3 and parts[1].lower() == "set":
            # /env set KEY value
            rest = command.split(maxsplit=2)[2] if len(command.split(maxsplit=2)) > 2 else ""
            key_value = rest.split(maxsplit=1)
            if len(key_value) < 2:
                await self._mount_message(
                    SystemMessage("Usage: /env set <KEY> <value>")
                )
            else:
                key, value = key_value[0].upper(), key_value[1]
                await self._env_set(key, value)
        elif len(parts) >= 3 and parts[1].lower() == "unset":
            # /env unset KEY
            key = parts[2].upper()
            await self._env_unset(key)
        else:
            await self._mount_message(
                SystemMessage(t("tui.env.usage"))
            )

    async def _env_list(self) -> None:
        """List all environment variables and their status."""
        import os

        from ieum.widgets.messages import SystemMessage

        lines = [f"{t('tui.env.status_header')}\n"]

        # Group by category
        categories = {
            "LLM Providers (Cloud)": [
                "OPENAI_API_KEY", "ANTHROPIC_API_KEY", "GOOGLE_API_KEY",
                "GROQ_API_KEY", "MISTRAL_API_KEY", "COHERE_API_KEY",
                "NVIDIA_API_KEY", "OPENROUTER_API_KEY", "DEEPSEEK_API_KEY",
                "UPSTAGE_API_KEY", "DASHSCOPE_API_KEY", "ZHIPUAI_API_KEY",
            ],
            "LLM Providers (Local)": [
                "OLLAMA_BASE_URL", "OLLAMA_MODEL",
                "LMSTUDIO_BASE_URL", "VLLM_BASE_URL",
            ],
            "Tools": ["TAVILY_API_KEY"],
            "Observability": ["LANGFUSE_PUBLIC_KEY", "LANGFUSE_SECRET_KEY", "LANGFUSE_HOST"],
        }

        for category, keys in categories.items():
            lines.append(f"[{category}]")
            for key in keys:
                value = os.environ.get(key)
                desc = self._ENV_KEYS.get(key, key)
                if value:
                    # Mask the value
                    masked = self._mask_value(value)
                    lines.append(f"  ✓ {key}: {masked}")
                else:
                    lines.append(f"  ✗ {key}: {t('tui.env.not_set')}")
            lines.append("")

        # Show .env file location
        env_path = self._get_env_file_path()
        lines.append(t("tui.env.config_file", path=env_path))
        lines.append(t("tui.env.set_command"))

        await self._mount_message(SystemMessage("\n".join(lines)))

    def _mask_value(self, value: str) -> str:
        """Mask a sensitive value for display."""
        if len(value) <= 8:
            return "*" * len(value)
        return value[:4] + "*" * (len(value) - 8) + value[-4:]

    def _get_env_file_path(self) -> Path:
        """Get the .env file path (project root > user home)."""
        # Check project .env first (current working directory)
        project_env = Path.cwd() / ".env"
        if project_env.exists():
            return project_env

        # Fall back to user home
        return Path.home() / ".ieum" / ".env"

    async def _env_set(self, key: str, value: str) -> None:
        """Set an environment variable and save to .env file."""
        import os

        from ieum.widgets.messages import SystemMessage

        # Validate key against whitelist to prevent arbitrary env var injection
        if key not in self._ENV_KEYS:
            allowed = ", ".join(sorted(self._ENV_KEYS.keys()))
            await self._mount_message(
                SystemMessage(
                    f"Cannot set '{key}': not an allowed environment variable.\n"
                    f"Allowed keys: {allowed}"
                )
            )
            return

        # Set in current environment
        os.environ[key] = value

        # Save to .env file
        env_path = self._get_env_file_path()

        # Ensure directory exists
        env_path.parent.mkdir(parents=True, exist_ok=True)

        # Read existing .env content
        existing_lines: list[str] = []
        if env_path.exists():
            try:
                existing_lines = env_path.read_text(encoding="utf-8").splitlines()
            except OSError:
                pass

        # Update or add the key
        key_found = False
        new_lines: list[str] = []
        for line in existing_lines:
            stripped = line.strip()
            if stripped.startswith(f"{key}=") or stripped.startswith(f"{key} ="):
                new_lines.append(f"{key}={value}")
                key_found = True
            else:
                new_lines.append(line)

        if not key_found:
            new_lines.append(f"{key}={value}")

        # Write back
        try:
            env_path.write_text("\n".join(new_lines) + "\n", encoding="utf-8")
            # Restrict permissions to owner-only (rw-------) since file contains secrets
            env_path.chmod(0o600)

            # Reload settings to apply changes immediately
            from ieum.config import reload_settings
            reload_settings()

            masked = self._mask_value(value)
            await self._mount_message(
                SystemMessage(t("tui.env.set_success", env_key=key, value=masked, path=env_path))
            )
        except OSError as e:
            await self._mount_message(SystemMessage(t("tui.env.save_failed", error=str(e))))

    async def _env_unset(self, key: str) -> None:
        """Remove an environment variable from .env file."""
        import os

        from ieum.widgets.messages import SystemMessage

        # Remove from current environment
        if key in os.environ:
            del os.environ[key]

        # Remove from .env file
        env_path = self._get_env_file_path()

        if not env_path.exists():
            from ieum.config import reload_settings
            reload_settings()
            await self._mount_message(SystemMessage(t("tui.env.unset_no_file", env_key=key)))
            return

        try:
            existing_lines = env_path.read_text(encoding="utf-8").splitlines()
        except OSError:
            existing_lines = []

        # Filter out the key
        new_lines = [
            line for line in existing_lines
            if not line.strip().startswith(f"{key}=") and not line.strip().startswith(f"{key} =")
        ]

        if len(new_lines) == len(existing_lines):
            from ieum.config import reload_settings
            reload_settings()
            await self._mount_message(SystemMessage(t("tui.env.not_configured", env_key=key)))
            return

        try:
            env_path.write_text("\n".join(new_lines) + "\n", encoding="utf-8")
            # Restrict permissions to owner-only (rw-------) since file contains secrets
            env_path.chmod(0o600)

            # Reload settings to apply changes immediately
            from ieum.config import reload_settings
            reload_settings()

            await self._mount_message(
                SystemMessage(t("tui.env.unset_success", env_key=key, path=env_path))
            )
        except OSError as e:
            await self._mount_message(SystemMessage(t("tui.env.save_failed", error=str(e))))
