from __future__ import annotations

from textual import on
from textual.containers import Vertical
from textual.message import Message
from textual.widgets import Button, Input, Select, Static

from ..errors import ProxmoxError
from ..models.workflow import WorkflowState
from ..services.base import ProxmoxService, Realm
from ..settings import AppSettings


class LoginView(Vertical):
    class Authenticated(Message):
        def __init__(self, username: str, realm: str) -> None:
            self.username = username
            self.realm = realm
            super().__init__()

    DEFAULT_CSS = """
    LoginView {
        width: 1fr;
        height: 1fr;
        padding: 1 2;
        align-horizontal: center;
    }

    #login-card {
        width: 80;
        max-width: 100%;
        border: round $accent;
        padding: 1 2;
    }

    #title {
        text-style: bold;
        margin-bottom: 1;
    }

    Input, Select, Button {
        margin-top: 1;
    }

    #status {
        margin-top: 1;
        color: $text-muted;
    }
    """

    def __init__(
        self,
        settings: AppSettings,
        workflow: WorkflowState,
        service: ProxmoxService,
    ) -> None:
        super().__init__()
        self._settings = settings
        self._workflow = workflow
        self._service = service

    def compose(self):
        with Vertical(id="login-card"):
            yield Static("Proxmox Login", id="title")
            yield Static(
                f"Mode: {self._service.mode} on {self._settings.sanitized_host}",
                id="mode",
            )
            yield Input(
                value=self._settings.proxmox_user or "",
                placeholder="Username",
                id="username",
            )
            yield Input(
                value=self._settings.proxmox_password or "",
                password=True,
                placeholder="Password",
                id="password",
            )
            yield Select[str](options=[], prompt="Realm", id="realm")
            yield Button("Connect", id="connect", variant="primary")
            yield Static("Loading realms...", id="status")

    def on_mount(self) -> None:
        username_input = self.query_one("#username", Input)
        self.call_after_refresh(self.app.set_focus, username_input)
        self.run_worker(self._load_realms, thread=True, exclusive=True)

    def _load_realms(self) -> None:
        try:
            realms = self._service.load_realms()
        except Exception as exc:
            self.app.call_from_thread(self._show_status, f"Failed to load realms: {exc}")
            return
        self.app.call_from_thread(self._set_realms, realms)

    def _set_realms(self, realms: list[Realm]) -> None:
        self._workflow.available_realms = [realm.name for realm in realms]
        options = [(realm.title, realm.name) for realm in realms]
        select = self.query_one("#realm", Select)
        select.set_options(options)

        preferred_realm = self._settings.proxmox_realm
        if preferred_realm and preferred_realm in self._workflow.available_realms:
            select.value = preferred_realm
        elif realms:
            default_realm = next((realm.name for realm in realms if realm.default), realms[0].name)
            select.value = default_realm

        self._show_status(f"Loaded {len(realms)} realm(s).")

    def _show_status(self, message: str) -> None:
        self.query_one("#status", Static).update(message)

    @on(Button.Pressed, "#connect")
    def on_connect_pressed(self) -> None:
        self._submit()

    @on(Input.Submitted, "#username")
    @on(Input.Submitted, "#password")
    def on_input_submitted(self) -> None:
        self._submit()

    @on(Select.Changed, "#realm")
    def on_realm_changed(self) -> None:
        # Keep the form keyboard friendly once realms have loaded.
        if self.app.focused is None:
            username_input = self.query_one("#username", Input)
            self.call_after_refresh(self.app.set_focus, username_input)

    def _submit(self) -> None:
        username = self.query_one("#username", Input).value.strip()
        password = self.query_one("#password", Input).value
        realm = self.query_one("#realm", Select).value
        if not username or not password or not isinstance(realm, str):
            self._show_status("Username, password, and realm are required.")
            return

        self._show_status("Authenticating...")
        self.run_worker(
            lambda: self._authenticate(username=username, password=password, realm=realm),
            thread=True,
            exclusive=True,
        )

    def _authenticate(self, *, username: str, password: str, realm: str) -> None:
        try:
            session = self._service.login(username, password, realm)
        except (ProxmoxError, ValueError) as exc:
            self.app.call_from_thread(self._show_status, f"Authentication failed: {exc}")
            return
        self.app.call_from_thread(self._mark_authenticated, session.username, realm)

    def _mark_authenticated(self, username: str, realm: str) -> None:
        self._workflow.authentication.username = username
        self._workflow.authentication.realm = realm
        self._workflow.authentication.authenticated = True
        self._show_status(f"Authenticated as {username}.")
        self.post_message(self.Authenticated(username, realm))
