"""Input widget for string and number configuration options."""

import re
from textual.message import Message
from textual.validation import ValidationResult, Validator
from textual.widgets import Input

from ..models import OptionType


class IntegerValidator(Validator):
    """Validator for integer values."""

    def validate(self, value: str) -> ValidationResult:
        """Validate that value is a valid integer."""
        if not value:
            return self.success()
        if re.match(r"^-?\d+$", value):
            return self.success()
        return self.failure("Must be an integer")


class FloatValidator(Validator):
    """Validator for float values."""

    def validate(self, value: str) -> ValidationResult:
        """Validate that value is a valid float."""
        if not value:
            return self.success()
        try:
            float(value)
            return self.success()
        except ValueError:
            return self.failure("Must be a number")


class ColorValidator(Validator):
    """Validator for hex color values."""

    def validate(self, value: str) -> ValidationResult:
        """Validate that value is a valid hex color."""
        if not value:
            return self.success()
        # Allow #RGB, #RRGGBB, or RRGGBB formats
        if re.match(r"^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$", value):
            return self.success()
        return self.failure("Must be a hex color (#RGB or #RRGGBB)")


class OptionInput(Input):
    """Input widget for string/number options with validation."""

    DEFAULT_CSS = """
    OptionInput {
        width: 100%;
        height: 3;
    }

    OptionInput:focus {
        border: solid $primary;
    }

    OptionInput.-invalid {
        border: solid $error;
    }

    OptionInput.-modified {
        border-left: wide $warning;
    }
    """

    class Changed(Message):
        """Message emitted when input value changes (on blur)."""

        def __init__(self, option_name: str, value: str, is_valid: bool) -> None:
            self.option_name = option_name
            self.value = value
            self.is_valid = is_valid
            super().__init__()

    def __init__(
        self,
        option_name: str,
        value: str = "",
        option_type: OptionType = OptionType.STRING,
        default: str = "",
        **kwargs
    ) -> None:
        """Initialize input widget.

        Args:
            option_name: Name of the configuration option
            value: Current value
            option_type: Type of the option for validation
            default: Default value for comparison
        """
        # Set up validators based on type
        validators = self._get_validators(option_type)

        # Set placeholder based on type
        placeholder = self._get_placeholder(option_type, default)

        super().__init__(
            value=value,
            placeholder=placeholder,
            validators=validators,
            **kwargs
        )

        self.option_name = option_name
        self.option_type = option_type
        self.default_value = default
        self._last_value = value

    def _get_validators(self, option_type: OptionType) -> list[Validator]:
        """Get validators for option type."""
        match option_type:
            case OptionType.INTEGER:
                return [IntegerValidator()]
            case OptionType.FLOAT:
                return [FloatValidator()]
            case OptionType.COLOR:
                return [ColorValidator()]
            case _:
                return []

    def _get_placeholder(self, option_type: OptionType, default: str) -> str:
        """Get placeholder text for option type."""
        if default:
            return f"Default: {default}"

        match option_type:
            case OptionType.INTEGER:
                return "Enter a number"
            case OptionType.FLOAT:
                return "Enter a decimal number"
            case OptionType.COLOR:
                return "#RRGGBB or #RGB"
            case OptionType.PATH:
                return "/path/to/file"
            case _:
                return "Enter value"

    def get_value(self) -> str:
        """Get the current input value."""
        return self.value

    def set_value(self, value: str) -> None:
        """Set the input value."""
        self.value = value
        self._last_value = value

    @property
    def is_modified(self) -> bool:
        """Check if value differs from default."""
        return self.value != self.default_value

    @property
    def is_valid(self) -> bool:
        """Check if current value is valid."""
        result = self.validate(self.value)
        return result.is_valid if result else True

    def on_blur(self) -> None:
        """Handle blur event - emit change if value changed."""
        if self.value != self._last_value:
            self._last_value = self.value
            self.post_message(self.Changed(
                option_name=self.option_name,
                value=self.value,
                is_valid=self.is_valid
            ))

        # Update modified class
        if self.is_modified:
            self.add_class("-modified")
        else:
            self.remove_class("-modified")
