from typing import Any, Callable

from cotation.acoustic.display.io_widget.input_interface import InputInterface

try:
	from typing import override
except ImportError:
	from typing_extensions import override  # noqa: F401

from PySide6.QtWidgets import (
	QSpinBox,
	QWidget,
)

DEFAULT_VALUE_TEXT = "Veuillez selectionner une valeur."


class IntInput(QSpinBox, InputInterface):
	"""
	IntInput is a custom QSpinBox widget implementing the InputInterface for integer input fields.
	Attributes:
		default_invalid_value (int): The value considered as invalid input (not directly used in this class).
	"""

	default_invalid_value: int

	def __init__(
		self,
		default_value: int = -1,
		default_is_invalid: bool = True,
		default_value_text: str = DEFAULT_VALUE_TEXT,
	):
		super().__init__()

		self.default_value = default_value
		self.default_is_invalid = default_is_invalid

		if default_is_invalid:
			self.setSpecialValueText(default_value_text)
		self.setMinimum(default_value)
		self.setValue(default_value)

		# Connect internal Qt signal to our callback handler using lambda to avoid connection warnings
		self.valueChanged.connect(lambda _: self._handle_value_changed())

	@override
	def get_widget(self) -> QWidget:
		"""
		Returns the QWidget instance associated with this component.

		:return: The current QWidget instance.
		"""
		return self

	@override
	def set_resize_callback(self, callback: Callable[[int], Any]) -> None:
		"""
		Sets a callback to be triggered when the widget is resized.

		Note: This widget does not emit resize events, so this method has no effect.

		:param callback: A function that takes an integer (new size) as argument.
		"""
		# IntInput doesn't emit resize events
		pass

	def get_input_value(self):
		"""
		Retrieves the current value from the input widget.

		Returns:
			int or float: The current value of the input, as returned by the `value()` method.
		"""
		return self.value()

	def set_input_value(self, value: int):
		"""
		Sets the value of the input widget.

		Parameters:
			value (int): The integer value to set in the input widget.

		This method updates the widget's displayed value to the specified integer.
		"""
		self.setValue(int(value))

	def get_is_filled(self) -> bool:
		"""
		Determines whether the input field is considered filled.

		Returns:
			bool: True if the input is filled (i.e., the default is valid and the current value
			differs from the default value), False otherwise.
		"""
		return not self.default_is_invalid or self.value() != self.default_value
