from functools import wraps
from typing import Callable
from typing_extensions import ParamSpec

from aiogram.types import KeyboardButton, InlineKeyboardButton
from aiogram.utils.keyboard import ReplyKeyboardBuilder, InlineKeyboardBuilder

P = ParamSpec("P")

def reply(function: Callable[P, list[list[str]]]):
	@wraps(function)
	def wrapper(*args: P.args, **kwargs: P.kwargs):
		builder = ReplyKeyboardBuilder()
		
		rows = function(*args, **kwargs)
		
		for row in rows:
			if len(row) > 10:
				raise ValueError("Reply keyboards can have a maximum of 10 buttons per column")
			
			builder.row(*[KeyboardButton(text=button) for button in row])

		return builder.as_markup()
		
	return wrapper

def inline(function: Callable[P, list[list[tuple[str, str]]]]):
	@wraps(function)
	def wrapper(*args: P.args, **kwargs: P.kwargs):
		builder = InlineKeyboardBuilder()
		
		rows = function(*args, **kwargs)
		
		for row in rows:
			if len(row) > 8:
				raise ValueError("Inline keyboards can have a maximum of 8 buttons per column")
				
			buttons = []

			for button in row:
				if len(button) != 2:
					raise ValueError("InlineKeyboardButton must be a tuple of (text, callback_data)")
				
				text = button[0]
				value = button[1]

				if value.startswith("t.me"):
					value = "https://" + value
				
				if value.startswith(("https://", "http://", "tg://")):
					buttons.append(InlineKeyboardButton(text=text, url=value))
				else:
					buttons.append(InlineKeyboardButton(text=text, callback_data=value))
			
			builder.row(*buttons)

		return builder.as_markup()
		
	return wrapper

__all__ = ["reply", "inline"]