"""Template build wizard screen."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Optional

from textual import work
from textual.app import ComposeResult
from textual.binding import Binding
from textual.containers import Horizontal, Vertical
from textual.screen import Screen
from textual.widgets import (
    Button,
    Footer,
    Header,
    Input,
    Label,
    OptionList,
    RadioButton,
    RadioSet,
    RichLog,
    Static,
)
from textual.widgets.option_list import Option


@dataclass
class BuildState:
    """State container for template build wizard."""

    distro: Optional[str] = None
    version: Optional[str] = None
    profile: str = "base"
    network_mode: str = "dhcp"
    template_name: Optional[str] = None
    template_id: Optional[int] = None
    vm_cores: int = 2
    vm_memory: int = 2048
    vm_disk_size: str = "10G"
    cloudinit_user: Optional[str] = None
    cloudinit_password: Optional[str] = None


class TemplateBuildScreen(Screen):
    """Multi-step wizard for building VM templates."""

    BINDINGS = [
        Binding("escape", "cancel", "Cancel", show=True),
    ]

    def __init__(self) -> None:
        super().__init__()
        self.state = BuildState()
        self.step = 0
        self.total_steps = 7

    def compose(self) -> ComposeResult:
        yield Header()
        with Vertical(classes="wizard-container"):
            yield Static("Build New Template", classes="wizard-title")
            yield Static("", id="step-indicator", classes="wizard-step")
            yield Vertical(id="wizard-content", classes="wizard-content")
            with Horizontal(classes="wizard-nav"):
                yield Button("Back", id="back", disabled=True)
                yield Button("Next", id="next", variant="primary")
                yield Button("Cancel", id="cancel")
        yield Footer()

    def on_mount(self) -> None:
        self._show_step(0)

    def _update_step_indicator(self) -> None:
        """Update the step indicator text."""
        step_names = [
            "Distribution",
            "Version",
            "Package Profile",
            "Network",
            "Configuration",
            "Credentials",
            "Confirm",
        ]
        name = step_names[self.step] if self.step < len(step_names) else "Build"
        indicator = self.query_one("#step-indicator", Static)
        indicator.update(f"Step {self.step + 1} of {self.total_steps}: {name}")

    def _show_step(self, step: int) -> None:
        """Display a specific wizard step."""
        self.step = step
        self._update_step_indicator()

        content = self.query_one("#wizard-content")
        content.remove_children()

        steps = [
            self._step_distribution,
            self._step_version,
            self._step_profile,
            self._step_network,
            self._step_config,
            self._step_credentials,
            self._step_confirm,
        ]

        if 0 <= step < len(steps):
            steps[step](content)

        # Update navigation buttons
        back_btn = self.query_one("#back", Button)
        next_btn = self.query_one("#next", Button)

        back_btn.disabled = step == 0
        next_btn.label = "Build" if step == len(steps) - 1 else "Next"

        # Focus the first interactive widget after mount completes
        self.set_timer(0.1, self._focus_content)

    def _focus_content(self) -> None:
        """Focus the first interactive widget in the wizard content area."""
        content = self.query_one("#wizard-content")
        for widget_class in (OptionList, RadioSet, Input):
            try:
                widget = content.query_one(widget_class)
                widget.focus()
                return
            except Exception:
                continue

    def _step_distribution(self, container: Vertical) -> None:
        """Step 1: Select distribution."""
        container.mount(Label("Select Distribution Family:"))

        distros = self.app.config.get_distro_list()
        options = [Option(display, id=distro_id) for distro_id, display in distros]

        option_list = OptionList(*options, id="distro-list")
        container.mount(option_list)

    def _step_version(self, container: Vertical) -> None:
        """Step 2: Select version."""
        if not self.state.distro:
            container.mount(Label("Error: No distribution selected"))
            return

        container.mount(Label(f"Select {self.state.distro.title()} Version:"))

        versions = self.app.config.get_version_list(self.state.distro)
        options = [Option(display, id=version_id) for version_id, display in versions]

        option_list = OptionList(*options, id="version-list")
        container.mount(option_list)

    def _step_profile(self, container: Vertical) -> None:
        """Step 3: Select package profile."""
        container.mount(Label("Select Package Profile:"))

        container.mount(
            RadioSet(
                RadioButton("Minimal - OS only, no extra packages", id="minimal"),
                RadioButton(
                    "Base - Essential tools (qemu-agent, cloud-init, curl, git)",
                    id="base",
                    value=True,
                ),
                RadioButton(
                    "Extended - DevOps tools (Docker, Terraform, kubectl, etc.)",
                    id="extended",
                ),
                id="profile-radio",
            )
        )

    def _step_network(self, container: Vertical) -> None:
        """Step 4: Select network configuration."""
        container.mount(Label("Select Network Configuration:"))

        container.mount(
            RadioSet(
                RadioButton(
                    "DHCP - Automatic IP assignment (Recommended)",
                    id="dhcp",
                    value=True,
                ),
                RadioButton(
                    "Static - Configure IP manually after deployment", id="static"
                ),
                RadioButton(
                    "Cloud-init - Let cloud-init manage networking (Advanced)",
                    id="cloudinit",
                ),
                id="network-radio",
            )
        )

        container.mount(
            Static(
                "\n[yellow]Note:[/yellow] DHCP is recommended for most use cases.\n"
                "Cloud-init networking can cause boot delays.",
                markup=True,
            )
        )

    def _step_config(self, container: Vertical) -> None:
        """Step 5: Configure template settings."""
        config = self.app.config

        # Generate default name
        default_name = f"{self.state.distro}-{self.state.version}-{self.state.profile}"
        if not self.state.template_name:
            self.state.template_name = default_name

        # Defaults
        default_cores = config.get_default_int("DEFAULT_VM_CORES", 2)
        is_desktop = self.state.version and "desktop" in self.state.version
        default_memory = 4096 if is_desktop else 2048
        default_disk = "25G" if is_desktop else "10G"

        container.mount(Label("Template Configuration:"))

        container.mount(Label("Template Name:"))
        container.mount(
            Input(value=self.state.template_name or default_name, id="template-name")
        )

        container.mount(Label("Template ID (leave empty for auto):"))
        container.mount(
            Input(
                value=str(self.state.template_id) if self.state.template_id else "",
                placeholder="Auto-assigned from 9200",
                id="template-id",
            )
        )

        container.mount(Label("CPU Cores:"))
        container.mount(Input(value=str(self.state.vm_cores or default_cores), id="cores"))

        container.mount(Label("Memory (MB):"))
        container.mount(
            Input(value=str(self.state.vm_memory or default_memory), id="memory")
        )

        container.mount(Label("Disk Size:"))
        container.mount(
            Input(value=self.state.vm_disk_size or default_disk, id="disk-size")
        )

    def _step_credentials(self, container: Vertical) -> None:
        """Step 6: Configure cloud-init credentials."""
        config = self.app.config

        default_user = config.get_default("DEFAULT_CLOUDINIT_USER", "admin")
        default_pass = config.get_default("DEFAULT_CLOUDINIT_PASSWORD", "")

        container.mount(Label("Cloud-init Default Credentials:"))
        container.mount(
            Static(
                "[dim]These credentials will be used for initial VM access.[/dim]",
                markup=True,
            )
        )

        container.mount(Label("Username:"))
        container.mount(
            Input(value=self.state.cloudinit_user or default_user, id="cloudinit-user")
        )

        container.mount(Label("Password:"))
        container.mount(
            Input(
                value=self.state.cloudinit_password or default_pass,
                password=True,
                id="cloudinit-password",
            )
        )

        container.mount(Label("Confirm Password:"))
        container.mount(Input(password=True, id="cloudinit-password-confirm"))

    def _step_confirm(self, container: Vertical) -> None:
        """Step 7: Confirmation summary."""
        container.mount(Label("Build Summary:", classes="summary-title"))

        summary = Vertical(classes="summary-panel")
        container.mount(summary)

        rows = [
            ("Distribution:", f"{self.state.distro} {self.state.version}"),
            ("Package Profile:", self.state.profile),
            ("Network Mode:", self.state.network_mode),
            ("Template Name:", self.state.template_name or "N/A"),
            (
                "Template ID:",
                str(self.state.template_id) if self.state.template_id else "Auto",
            ),
            ("CPU Cores:", str(self.state.vm_cores)),
            ("Memory:", f"{self.state.vm_memory} MB"),
            ("Disk Size:", self.state.vm_disk_size),
            ("Cloud-init User:", self.state.cloudinit_user or "N/A"),
            ("Cloud-init Pass:", "********" if self.state.cloudinit_password else "N/A"),
        ]

        for label, value in rows:
            summary.mount(Static(f"  {label:20} {value}"))

        container.mount(
            Static(
                "\n[yellow]Ready to build template.[/yellow]\n"
                "Press 'Build' to start the packer build process.",
                markup=True,
            )
        )

    def on_option_list_option_selected(
        self, event: OptionList.OptionSelected
    ) -> None:
        """Handle option list selection and auto-advance."""
        option_id = event.option.id

        if event.option_list.id == "distro-list":
            self.state.distro = option_id
            self._advance_step()
        elif event.option_list.id == "version-list":
            self.state.version = option_id
            self._advance_step()

    def on_radio_set_changed(self, event: RadioSet.Changed) -> None:
        """Handle radio button changes."""
        if event.radio_set.id == "profile-radio":
            self.state.profile = event.pressed.id
        elif event.radio_set.id == "network-radio":
            self.state.network_mode = event.pressed.id

    def _collect_step_data(self) -> bool:
        """Collect data from current step's inputs.

        Returns:
            True if validation passed, False otherwise.
        """
        if self.step == 4:  # Config step
            try:
                self.state.template_name = self.query_one("#template-name", Input).value
                template_id_str = self.query_one("#template-id", Input).value
                if template_id_str:
                    self.state.template_id = int(template_id_str)
                self.state.vm_cores = int(self.query_one("#cores", Input).value)
                self.state.vm_memory = int(self.query_one("#memory", Input).value)
                self.state.vm_disk_size = self.query_one("#disk-size", Input).value
            except ValueError:
                self.notify("Invalid number format", severity="error")
                return False

        elif self.step == 5:  # Credentials step
            self.state.cloudinit_user = self.query_one("#cloudinit-user", Input).value
            password = self.query_one("#cloudinit-password", Input).value
            confirm = self.query_one("#cloudinit-password-confirm", Input).value

            if password != confirm:
                self.notify("Passwords do not match", severity="error")
                return False

            self.state.cloudinit_password = password

        return True

    def _advance_step(self) -> None:
        """Advance to next step."""
        if not self._collect_step_data():
            return

        if self.step < self.total_steps - 1:
            self._show_step(self.step + 1)
        else:
            self._start_build()

    def on_button_pressed(self, event: Button.Pressed) -> None:
        """Handle button presses."""
        if event.button.id == "back":
            if self.step > 0:
                self._show_step(self.step - 1)
        elif event.button.id == "next":
            self._advance_step()
        elif event.button.id == "cancel":
            self.action_cancel()

    def action_cancel(self) -> None:
        """Cancel and return to main menu."""
        self.app.pop_screen()

    def _start_build(self) -> None:
        """Start the packer build process."""
        self.app.push_screen(BuildProgressScreen(self.state))


class BuildProgressScreen(Screen):
    """Screen showing build progress and output."""

    BINDINGS = [
        Binding("escape", "back", "Back (when complete)", show=True),
    ]

    def __init__(self, state: BuildState) -> None:
        super().__init__()
        self.state = state
        self.build_complete = False
        self.build_success = False

    def compose(self) -> ComposeResult:
        yield Header()
        with Vertical(classes="progress-container"):
            yield Static(
                f"Building: {self.state.template_name}", classes="progress-title"
            )
            yield RichLog(id="output", classes="progress-output", highlight=True)
            with Horizontal(classes="wizard-nav"):
                yield Button("Close", id="close", disabled=True)
        yield Footer()

    def on_mount(self) -> None:
        self.run_build()

    @work(exclusive=True, exit_on_error=False)
    async def run_build(self) -> None:
        """Run the packer build."""
        output = self.query_one("#output", RichLog)

        # Get or auto-assign template ID
        if not self.state.template_id:
            self.state.template_id = await self.app.proxmox.find_next_vmid(9200)
            self.app.call_later(
                output.write, f"Auto-assigned template ID: {self.state.template_id}"
            )

        def on_line(line: str) -> None:
            self.app.call_later(output.write, line)

        self.app.call_later(output.write, "Starting packer build...")
        self.app.call_later(output.write, "")

        result = await self.app.script_runner.run_packer_build(
            distro=self.state.distro,
            version=self.state.version,
            template_id=self.state.template_id,
            template_name=self.state.template_name,
            cores=self.state.vm_cores,
            memory=self.state.vm_memory,
            disk_size=self.state.vm_disk_size,
            package_profile=self.state.profile,
            on_output=on_line,
        )

        self.build_complete = True
        self.build_success = result == 0

        if result == 0:
            self.app.call_later(output.write, "")
            self.app.call_later(output.write, "[green]Build completed successfully![/green]")
        else:
            self.app.call_later(output.write, "")
            self.app.call_later(output.write, f"[red]Build failed with exit code: {result}[/red]")

        # Enable close button
        self.app.call_later(self._enable_close)

    def _enable_close(self) -> None:
        """Enable the close button."""
        self.query_one("#close", Button).disabled = False

    def on_button_pressed(self, event: Button.Pressed) -> None:
        if event.button.id == "close":
            # Pop both progress screen and wizard screen
            self.app.pop_screen()
            self.app.pop_screen()

    def action_back(self) -> None:
        if self.build_complete:
            self.app.pop_screen()
            self.app.pop_screen()
