"""
Comprehensive binding tests for all bindable FastHTML components.

This test suite covers:
- Input (text) - already tested
- Checkbox - already tested
- Textarea
- Select (single)
- Select (multiple)
- Range (slider)
- Radio buttons
- Button
- Input with Datalist (combobox)
"""

from dataclasses import dataclass

import pytest
from fasthtml.components import (
  Input, Label, Textarea
)
from fasthtml.fastapp import fast_app

from myfasthtml.controls.helpers import mk
from myfasthtml.core.bindings import Binding
from myfasthtml.test.testclient import MyTestClient


@dataclass
class Data:
  value: str = "hello world"


@dataclass
class NumericData:
  value: int = 50


@dataclass
class BoolData:
  value: bool = True


@dataclass
class ListData:
  value: list = None
  
  def __post_init__(self):
    if self.value is None:
      self.value = []


@pytest.fixture
def test_app():
  test_app, rt = fast_app(default_hdrs=False)
  return test_app


@pytest.fixture
def rt(test_app):
  return test_app.route


@pytest.fixture
def user(test_app):
  return MyTestClient(test_app)


class TestBindingEdgeCases:
  """Tests for edge cases and special scenarios."""
  
  def test_multiple_components_bind_to_same_data(self, user, rt):
    """
    Multiple different components can bind to the same data object.
    """
    
    @rt("/")
    def index():
      data = Data("synchronized")
      
      input_elt = Input(name="input_name")
      textarea_elt = Textarea(name="textarea_name")
      label_elt = Label()
      
      mk.manage_binding(input_elt, Binding(data))
      mk.manage_binding(textarea_elt, Binding(data))
      mk.manage_binding(label_elt, Binding(data))
      
      return input_elt, textarea_elt, label_elt
    
    user.open("/")
    user.should_see("synchronized")
    
    # Change via input
    testable_input = user.find_element("input")
    testable_input.send("changed via input")
    user.should_see("changed via input")
    
    # Change via textarea
    testable_textarea = user.find_element("textarea")
    testable_textarea.send("changed via textarea")
    user.should_see("changed via textarea")
  
  def test_component_without_name_attribute(self, user, rt):
    """
    Component without name attribute should handle gracefully.
    """
    
    @rt("/")
    def index():
      data = Data("test")
      # Input without name - should not crash
      input_elt = Input()  # No name attribute
      label_elt = Label()
      
      mk.manage_binding(label_elt, Binding(data))
      
      return input_elt, label_elt
    
    user.open("/")
    user.should_see("test")
  
  def test_binding_with_initial_empty_string(self, user, rt):
    """
    Binding should work correctly with empty string initial values.
    """
    
    @rt("/")
    def index():
      data = Data("")
      input_elt = Input(name="input_name")
      label_elt = Label()
      
      mk.manage_binding(input_elt, Binding(data))
      mk.manage_binding(label_elt, Binding(data))
      
      return input_elt, label_elt
    
    user.open("/")
    
    testable_input = user.find_element("input")
    testable_input.send("now has value")
    user.should_see("now has value")
  
  def test_binding_with_special_characters(self, user, rt):
    """
    Binding should handle special characters correctly.
    """
    
    @rt("/")
    def index():
      data = Data("Hello")
      input_elt = Input(name="input_name")
      label_elt = Label()
      
      mk.manage_binding(input_elt, Binding(data))
      mk.manage_binding(label_elt, Binding(data))
      
      return input_elt, label_elt
    
    user.open("/")
    
    testable_input = user.find_element("input")
    testable_input.send("Special: <>&\"'")
    user.should_see("Special: <>&\"'")
