from dataclasses import dataclass
from typing import Any

import pytest
from fasthtml.components import *
from fasthtml.fastapp import fast_app

from myfasthtml.controls.helpers import mk
from myfasthtml.core.bindings import Binding
from myfasthtml.core.commands import Command
from myfasthtml.test.matcher import matches
from myfasthtml.test.testclient import MyTestClient


@dataclass
class Data:
  value: Any


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


@pytest.fixture()
def rt(user):
  return user.app.route


def test_i_can_mk_button():
  button = mk.button('button')
  expected = Button('button')
  
  assert matches(button, expected)


def test_i_can_mk_button_with_attrs():
  button = mk.button('button', id="button_id", class_="button_class")
  expected = Button('button', id="button_id", class_="button_class")
  assert matches(button, expected)


def test_i_can_mk_button_with_command(user, rt):
  def new_value(value): return value
  
  command = Command('test', 'TestingCommand', new_value, "this is my new value")
  
  @rt('/')
  def get(): return mk.button('button', command)
  
  user.open("/")
  user.should_see("button")
  
  user.find_element("button").click()
  user.should_see("this is my new value")


class TestingBindings:
  @pytest.fixture()
  def data(self):
    return Data("value")
  
  def test_i_can_bind_an_input(self, data):
    elt = Input(name="input_elt", value="hello")
    binding = Binding(data, "value")
    elt = mk.manage_binding(elt, binding)
    
    # element is updated
    assert "hx-post" in elt.attrs
    assert "hx-vals" in elt.attrs
    assert "b_id" in elt.attrs["hx-vals"]
    
    # binding is also updated
    assert binding.ft == elt
    assert binding.ft_name == "input_elt"
    
  def test_i_can_bind_none_input(self, data):
    elt = Label("hello", name="input_elt")
    binding = Binding(data, "value")
    elt = mk.manage_binding(elt, binding)
    
    # element is updated
    assert "hx-post" not in elt.attrs
    assert "hx-get" not in elt.attrs
    
    # binding is also updated
    assert binding.ft == elt
    assert binding.ft_name == "input_elt"
    
