"""Cleaver panel widget for Cleave execution parameters."""

from collections.abc import Callable
from dataclasses import dataclass
from pathlib import Path
from typing import Literal

from textual.app import ComposeResult
from textual.containers import Vertical
from textual.widgets import Button, Checkbox, Input, Label, RadioButton, RadioSet, Select


@dataclass
class CleaveParams:
    """Parameters for Cleave execution."""

    parallel: bool = True
    dry_run: bool = False
    max_depth: int = 3
    model: Literal["sonnet", "opus", "haiku"] = "opus"
    selected_calf: Path | None = None


class CleaverPanel(Vertical):
    """Panel with Cleave execution parameters.

    The "Cleaver" is the sub-panel within sLaughterHouse that configures
    how directives are processed through the Cleave skill.

    Interface for sibling integration:
        get_params() -> CleaveParams - Get current parameter values
        get_selected_calf() -> Path | None - Get selected .calf file
        set_calf_files(files: list[Path]) - Update dropdown options
    """

    DEFAULT_CSS = """
    CleaverPanel {
        height: 100%;
        padding: 0 1;
    }

    CleaverPanel Label {
        margin-bottom: 0;
    }

    CleaverPanel Select {
        margin-bottom: 1;
        width: 100%;
    }

    CleaverPanel Checkbox {
        margin-bottom: 0;
    }

    CleaverPanel .options-row {
        height: auto;
        margin-bottom: 1;
    }

    CleaverPanel .options-row Label {
        margin-bottom: 0;
    }

    CleaverPanel .options-row Input {
        width: 6;
    }

    CleaverPanel RadioSet {
        margin-bottom: 1;
        height: auto;
    }

    CleaverPanel #cleave-button {
        width: 100%;
        dock: bottom;
    }
    """

    # Callback for when CLEAVE button is pressed
    on_cleave: Callable[["CleaveParams"], None] | None = None

    def compose(self) -> ComposeResult:
        """Compose the parameter controls."""
        # File selector
        yield Select(
            [],
            prompt="Select .calf file",
            id="calf-select",
            allow_blank=True,
        )

        # Options
        with Vertical(classes="options-row"):
            yield Checkbox("Parallel", id="parallel-check", value=True)
            yield Checkbox("Dry run", id="dry-run-check", value=False)
            yield Label("Max depth:")
            yield Input("3", id="max-depth-input", type="integer", max_length=2)

        # Model selection
        yield Label("Model:")
        with RadioSet(id="model-radio"):
            yield RadioButton("Sonnet", id="model-sonnet")
            yield RadioButton("Opus", id="model-opus", value=True)
            yield RadioButton("Haiku", id="model-haiku")

        # CLEAVE button
        yield Button("CLEAVE", id="cleave-button", variant="primary")

    def on_button_pressed(self, event: Button.Pressed) -> None:
        """Handle button presses."""
        if event.button.id == "cleave-button" and self.on_cleave is not None:
            self.on_cleave(self.get_params())

    def get_params(self) -> CleaveParams:
        """Get current parameter values.

        Returns:
            CleaveParams with current UI state
        """
        # Get checkbox values
        parallel = self.query_one("#parallel-check", Checkbox).value
        dry_run = self.query_one("#dry-run-check", Checkbox).value

        # Get max depth
        depth_input = self.query_one("#max-depth-input", Input)
        try:
            max_depth = int(depth_input.value)
        except ValueError:
            max_depth = 3

        # Get model selection
        radio_set = self.query_one("#model-radio", RadioSet)
        model: Literal["sonnet", "opus", "haiku"] = "opus"
        if radio_set.pressed_button:
            button_id = radio_set.pressed_button.id
            if button_id == "model-sonnet":
                model = "sonnet"
            elif button_id == "model-haiku":
                model = "haiku"
            else:
                model = "opus"

        # Get selected calf file
        selected_calf = self.get_selected_calf()

        return CleaveParams(
            parallel=parallel,
            dry_run=dry_run,
            max_depth=max_depth,
            model=model,
            selected_calf=selected_calf,
        )

    def get_selected_calf(self) -> Path | None:
        """Get the currently selected .calf file.

        Returns:
            Path to selected file, or None if nothing selected
        """
        select = self.query_one("#calf-select", Select)
        if select.value and select.value != Select.BLANK:
            return Path(select.value)
        return None

    def set_calf_files(self, files: list[Path]) -> None:
        """Update the dropdown with available .calf files.

        Args:
            files: List of paths to .calf files
        """
        select = self.query_one("#calf-select", Select)
        options = [(f.name, str(f)) for f in files]
        select.set_options(options)
