"""Test validation helper functions."""

from __future__ import annotations

from hipr import (
  Ge,
  Hyper,
  Le,
  configurable,
  validate_config,
)


def test_validate_config_valid_data() -> None:
  """Test validation with valid data."""

  @configurable
  def func(
    x: Hyper[int, Ge[0], Le[100]] = 10,
    y: Hyper[float] = 0.5,
  ) -> float:
    return x * y

  valid, errors = validate_config(func.Config, {"x": 50, "y": 0.75})
  assert valid
  assert len(errors) == 0


def test_validate_config_invalid_data() -> None:
  """Test validation with invalid data."""

  @configurable
  def func(x: Hyper[int, Ge[0], Le[100]] = 10) -> int:
    return x

  valid, errors = validate_config(func.Config, {"x": 150})
  assert not valid
  assert len(errors) > 0


def test_validate_config_missing_field_with_default() -> None:
  """Test validation with missing field that has default."""

  @configurable
  def func(x: Hyper[int] = 10, y: Hyper[int] = 20) -> int:
    return x + y

  # Missing fields with defaults should be valid
  valid, _errors = validate_config(func.Config, {"x": 5})
  assert valid

  valid, _errors = validate_config(func.Config, {})
  assert valid


def test_validate_config_type_error() -> None:
  """Test validation with wrong type."""

  @configurable
  def func(x: Hyper[int] = 10) -> int:
    return x

  valid, errors = validate_config(func.Config, {"x": "not an int"})
  assert not valid
  assert len(errors) > 0


def test_validate_config_multiple_errors() -> None:
  """Test validation with multiple errors."""

  @configurable
  def func(
    x: Hyper[int, Ge[0]] = 10,
    y: Hyper[float, Ge[0.0], Le[1.0]] = 0.5,
  ) -> float:
    return x * y

  valid, errors = validate_config(func.Config, {"x": -5, "y": 2.0})
  assert not valid
  assert len(errors) >= 2  # At least one error for each field


def test_validate_config_with_class() -> None:
  """Test validation with class configurations."""

  @configurable
  class Model:
    def __init__(self, value: Hyper[int, Ge[1]] = 10) -> None:
      self.value = value

  # Valid config
  valid, _errors = validate_config(Model.Config, {"value": 5})
  assert valid

  # Invalid config
  valid, _errors = validate_config(Model.Config, {"value": 0})
  assert not valid
