"""
Host Tab for software management
"""

import subprocess
from textual.widgets import Static, Button, DataTable, Label
from textual.containers import Horizontal
from textual.app import ComposeResult
from textual import work
from ..core.host import HostManager


class HostTab(Static):
    """Tab for host services and software management"""

    # State tracking
    selected_software: str | None = None
    software_data: dict = {}  # {key: {name, installed, version, install_cmd}}

    def compose(self) -> ComposeResult:
        yield Label("Host Software Management", id="host-title")
        yield Label("Press **R** to refresh", id="host-help")

        yield Label("Software (select row to manage)", id="software-section-title")
        yield DataTable(id="software-table", cursor_type="row")
        yield Label("Selected: [dim]None[/]", id="software-selected-label")
        yield Horizontal(
            Button("Install", id="software-install", variant="success", disabled=True),
            Button("Uninstall", id="software-uninstall", variant="error", disabled=True),
            id="software-buttons"
        )

    def on_mount(self) -> None:
        """Initialize software table when tab is mounted"""
        self.refresh_software()

    def on_data_table_row_selected(self, event: DataTable.RowSelected) -> None:
        """Handle row selection in the software table"""
        if event.data_table.id != "software-table":
            return

        self.selected_software = str(event.row_key.value) if event.row_key else None
        self.update_selected_label()
        self.update_button_states()

    def update_selected_label(self) -> None:
        """Update the selected software label"""
        try:
            label = self.query_one("#software-selected-label", Label)
            if self.selected_software:
                data = self.software_data.get(self.selected_software, {})
                name = data.get("name", self.selected_software)
                installed = data.get("installed", False)
                version = data.get("version", "")
                status = f"[green]Installed ({version})[/]" if installed else "[red]Not installed[/]"
                label.update(f"Selected: [bold]{name}[/] - {status}")
            else:
                label.update("Selected: [dim]None[/]")
        except Exception:
            pass

    def update_button_states(self) -> None:
        """Enable/disable buttons based on selected software state"""
        try:
            install_btn = self.query_one("#software-install", Button)
            uninstall_btn = self.query_one("#software-uninstall", Button)

            if not self.selected_software:
                install_btn.disabled = True
                uninstall_btn.disabled = True
                return

            data = self.software_data.get(self.selected_software, {})
            installed = data.get("installed", False)
            has_install = bool(data.get("install_cmd"))
            has_uninstall = bool(data.get("uninstall_cmd"))

            # Enable install if not installed and has install command
            install_btn.disabled = installed or not has_install
            # Enable uninstall if installed and has uninstall command
            uninstall_btn.disabled = not installed or not has_uninstall
        except Exception:
            pass

    def refresh_software(self) -> None:
        """Refresh software table"""
        try:
            table = self.query_one("#software-table", DataTable)
            table.clear(columns=True)
            table.add_column("Software", width=25)
            table.add_column("Status", width=15)
            table.add_column("Version", width=40)

            software = HostManager.check_required_software()
            self.software_data = {}

            for item in software:
                key = item["key"]
                self.software_data[key] = item
                installed_str = "[green]Yes[/]" if item["installed"] else "[red]No[/]"
                table.add_row(item["name"], installed_str, item["version"], key=key)

            # Update button states after refresh
            self.update_button_states()
        except Exception:
            pass

    def on_button_pressed(self, event: Button.Pressed) -> None:
        """Handle button presses"""
        if event.button.id == "software-install":
            self.install_software()
        elif event.button.id == "software-uninstall":
            self.uninstall_software()

    def install_software(self) -> None:
        """Install selected software"""
        if not self.selected_software:
            return

        data = self.software_data.get(self.selected_software, {})
        install_cmd = data.get("install_cmd")
        if not install_cmd:
            self.notify(f"No install command for {data.get('name', self.selected_software)}", severity="error")
            return

        software_name = data.get('name', self.selected_software)
        self.notify(f"Installing {software_name}...", severity="information")
        self._do_install_worker(install_cmd, software_name)

    @work(thread=True)
    def _do_install_worker(self, install_cmd: str, software_name: str) -> None:
        """Worker to run install command"""
        try:
            result = subprocess.run(
                install_cmd,
                shell=True,
                capture_output=True,
                text=True
            )
            if result.returncode == 0:
                self.app.call_from_thread(
                    self.notify, f"Successfully installed {software_name}", severity="information"
                )
            else:
                self.app.call_from_thread(
                    self.notify, f"Failed to install: {result.stderr[:100]}", severity="error"
                )
        except Exception as e:
            self.app.call_from_thread(
                self.notify, f"Failed to install: {e}", severity="error"
            )
        self.app.call_from_thread(self.refresh_software)

    def uninstall_software(self) -> None:
        """Uninstall selected software"""
        if not self.selected_software:
            return

        data = self.software_data.get(self.selected_software, {})
        uninstall_cmd = data.get("uninstall_cmd")
        if not uninstall_cmd:
            self.notify(f"No uninstall command for {data.get('name', self.selected_software)}", severity="error")
            return

        software_name = data.get('name', self.selected_software)
        self.notify(f"Uninstalling {software_name}...", severity="information")
        self._do_uninstall_worker(uninstall_cmd, software_name)

    @work(thread=True)
    def _do_uninstall_worker(self, uninstall_cmd: str, software_name: str) -> None:
        """Worker to run uninstall command"""
        try:
            result = subprocess.run(
                uninstall_cmd,
                shell=True,
                capture_output=True,
                text=True
            )
            if result.returncode == 0:
                self.app.call_from_thread(
                    self.notify, f"Successfully uninstalled {software_name}", severity="information"
                )
            else:
                self.app.call_from_thread(
                    self.notify, f"Failed to uninstall: {result.stderr[:100]}", severity="error"
                )
        except Exception as e:
            self.app.call_from_thread(
                self.notify, f"Failed to uninstall: {e}", severity="error"
            )
        self.app.call_from_thread(self.refresh_software)
