"""iTerm2 terminal adapter for Portal external integrations."""

from __future__ import annotations

import asyncio
import json
import os
import subprocess
from pathlib import Path
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    from portal.core.domain.models.color import WorktreeColor


class ITermAdapter:
    """Adapter for iTerm2 integration."""

    def is_available(self) -> bool:
        """Check if iTerm is available for scripting."""
        if os.environ.get("TERM_PROGRAM") == "iTerm.app":
            return True

        try:
            result = subprocess.run(
                [
                    "osascript",
                    "-e",
                    'tell application "System Events" to name of application processes',
                ],
                capture_output=True,
                text=True,
                timeout=2,
            )
            if result.returncode == 0 and "iTerm" in result.stdout:
                return True

            result = subprocess.run(
                [
                    "osascript",
                    "-e",
                    'tell application "Finder" to name of application file id "com.googlecode.iterm2"',
                ],
                capture_output=True,
                text=True,
                timeout=2,
            )
            return result.returncode == 0
        except Exception:
            return False

    async def open_in_new_tab(
        self, worktree_path: Path, color: WorktreeColor, command: str | None = None
    ) -> bool:
        """Open a new iTerm tab with specified directory and tab color only."""
        if not self.is_available():
            return False

        safe_name = self._sanitize_applescript_string(f"{worktree_path.name} ({color.name})")
        if len(safe_name) > 100:
            safe_name = safe_name[:97] + "..."

        r, g, b = color.rgb
        if not all(0 <= val <= 255 for val in (r, g, b)):
            return False

        safe_path = self._sanitize_applescript_string(str(worktree_path))

        if command:
            safe_command = self._sanitize_applescript_string(command)
            # Add space prefix to avoid history
            command_line = f'write text " {safe_command}"'
        else:
            command_line = ""

        # iTerm2 OSC escape sequences for tab color
        # Use a space prefix to avoid saving to shell history (works in bash/zsh with HISTCONTROL=ignorespace)
        set_tab_color = f" printf '\\\\033]6;1;bg;red;brightness;{r}\\\\a'"
        set_tab_color += f" && printf '\\\\033]6;1;bg;green;brightness;{g}\\\\a'"
        set_tab_color += f" && printf '\\\\033]6;1;bg;blue;brightness;{b}\\\\a'"
        set_tab_color += " && clear"  # Clear the terminal after setting colors

        script = f"""
        tell application "iTerm"
            tell current window
                set newTab to (create tab with default profile)
                tell current session of newTab
                    write text " cd \\"{safe_path}\\""
                    write text "{set_tab_color}"
                    set name to "{safe_name}"
                    {command_line}
                end tell
            end tell
        end tell
        """

        try:
            process = await asyncio.create_subprocess_exec(
                "osascript",
                "-e",
                script,
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE,
            )
            stdout, stderr = await asyncio.wait_for(process.communicate(), timeout=10)
            return process.returncode == 0
        except (TimeoutError, Exception):
            return False

    async def apply_color(self, worktree_path: Path, color: WorktreeColor) -> bool:
        """Apply color to current iTerm tab (deprecated, kept for compatibility)."""
        return await self.open_in_new_tab(worktree_path, color)

    async def set_badge(self, text: str) -> bool:
        """Set iTerm badge text with validation."""
        if not self.is_available():
            return False

        # Sanitize badge text for security
        safe_text = self._sanitize_applescript_string(text)
        if len(safe_text) > 50:  # Badge text should be short
            safe_text = safe_text[:47] + "..."

        try:
            badge_text = f"\033]1337;SetBadgeFormat={safe_text}\a"
            print(badge_text, end="", flush=True)
            return True
        except Exception:
            return False

    async def create_profile(self, name: str, color: WorktreeColor) -> bool:
        """Create iTerm dynamic profile with security validation."""
        profile_dir = Path.home() / "Library/Application Support/iTerm2/DynamicProfiles"

        # Validate inputs
        safe_name = self._sanitize_applescript_string(name)
        if len(safe_name) > 100:
            return False

        # Validate RGB values
        r, g, b = color.rgb
        if not all(0 <= val <= 255 for val in (r, g, b)):
            return False

        try:
            profile_dir.mkdir(parents=True, exist_ok=True)
        except Exception:
            return False

        # Create secure profile without command execution
        safe_guid = f"portal-{safe_name.lower().replace('/', '-').replace(' ', '-')}"[:50]
        profile = {
            "Profiles": [
                {
                    "Name": f"Portal - {safe_name}",
                    "Guid": safe_guid,
                    "Use Tab Color": True,
                    "Tab Color": {
                        "Red Component": r / 255.0,
                        "Green Component": g / 255.0,
                        "Blue Component": b / 255.0,
                    },
                    "Badge Text": safe_name,
                    "Tags": ["portal", color.name.lower()],
                }
            ]
        }

        try:
            safe_filename = f"portal-{safe_name.replace('/', '-').replace(' ', '-')}"[:50]
            profile_file = profile_dir / f"{safe_filename}.json"
            with open(profile_file, "w", encoding="utf-8") as f:
                json.dump(profile, f, indent=2)
            return True
        except Exception:
            return False

    def get_status(self) -> dict[str, Any]:
        """Get iTerm integration status."""
        return {
            "available": self.is_available(),
            "name": "iTerm2",
            "version": self._get_iterm_version(),
            "features": {
                "tab_colors": self.is_available(),
                "dynamic_profiles": self._check_dynamic_profiles_support(),
                "badges": self.is_available(),
            },
        }

    def _get_iterm_version(self) -> str:
        """Get iTerm version if available."""
        if not self.is_available():
            return "Not available"

        try:
            result = subprocess.run(
                ["osascript", "-e", 'tell application "iTerm" to get version'],
                capture_output=True,
                text=True,
                timeout=5,
            )
            if result.returncode == 0:
                return result.stdout.strip()
        except Exception:
            pass

        return "Unknown"

    def _sanitize_applescript_string(self, text: str) -> str:
        """Sanitize string for safe AppleScript usage."""
        # Remove or escape dangerous characters
        text = text.replace('"', '\\"').replace("'", "\\'")
        text = text.replace("\n", " ").replace("\r", " ")
        # Remove control characters
        import re

        text = re.sub(r"[\x00-\x1f\x7f-\x9f]", "", text)
        return text

    def _check_dynamic_profiles_support(self) -> bool:
        """Check if dynamic profiles directory exists."""
        profile_dir = Path.home() / "Library/Application Support/iTerm2/DynamicProfiles"
        return profile_dir.exists() or self.is_available()
