from rich.console import Console, RenderableType
from rich.text import Text
from rich.align import Align
from rich.padding import Padding
import os
import readchar

_console = Console()

def _style(
    object,
    color = "#ffffff",
    bold = False,
    italic = False,
    underline = False,
    strike = False,
    reverse = False,
    alignment = "left",
    padding = 0,
    top_padding = None,
    right_padding = None,
    bottom_padding = None,
    left_padding = None,
    plain_text = False
):
    def apply_text_styles(object):
        styleable = Text()
        if isinstance(object, str):
            style_parts = [color]
            if bold: style_parts.append("bold")
            if italic: style_parts.append("italic")
            if underline: style_parts.append("underline")
            if strike: style_parts.append("strike")
            if reverse: style_parts.append("reverse")
            style = " ".join(style_parts)
            current_segment = ""
            for character in object:
                if character == " ":
                    if current_segment:
                        styleable.append(current_segment, style = style)
                        current_segment = ""
                    styleable.append(" ")
                else: current_segment += character
            if current_segment: styleable.append(current_segment, style=style)
            return styleable
        elif isinstance(object, list):
            for segment, segment_style in object:
                style_parts = [segment_style.get("color", color)]
                if segment_style.get("bold"): style_parts.append("bold")
                if segment_style.get("italic"): style_parts.append("italic")
                if segment_style.get("underline"): style_parts.append("underline")
                if segment_style.get("strike"): style_parts.append("strike")
                if segment_style.get("reverse"): style_parts.append("reverse")
                style = " ".join(style_parts)
                current_segment = ""
                for character in segment:
                    if character == " ":
                        if current_segment:
                            styleable.append(current_segment, style = style)
                            current_segment = ""
                        styleable.append(" ")
                    else: current_segment += character
                if current_segment: styleable.append(current_segment, style = style)
            return styleable
    
    def apply_alignment(alignable): return Align(alignable, alignment)
    
    def apply_padding(paddable):
        final_padding = (
            top_padding if top_padding is not None else padding,
            (right_padding if right_padding is not None else padding) * 2,
            bottom_padding if bottom_padding is not None else padding,
            (left_padding if left_padding is not None else padding) * 2
        )
        return Padding(paddable, final_padding)
    
    if plain_text:
        styled = apply_text_styles(object)
        return styled
    if isinstance(object, (str, list)):
        styled = apply_text_styles(object)
        aligned = apply_alignment(styled)
        padded = apply_padding(aligned)
        return padded
    if isinstance(object, RenderableType):
        aligned = apply_alignment(object)
        padded = apply_padding(aligned)
        return padded
    styled = apply_text_styles(str(object))
    aligned = apply_alignment(styled)
    padded = apply_padding(aligned)
    return padded

def print(
    *objects,
    color = "#ffffff",
    bold = False,
    italic = False,
    underline = False,
    strike = False,
    reverse = False,
    alignment = "left",
    padding = 0,
    top_padding = None,
    right_padding = None,
    bottom_padding = None,
    left_padding = None,
    plain_text = False,
    separator = " ",
    end = "\n",
    **kwargs
):
    renderables = []
    for object in objects:
        renderables.append(_style(
            object = object,
            color = color,
            bold = bold,
            italic = italic,
            underline = underline,
            strike = strike,
            reverse = reverse,
            alignment = alignment,
            padding = padding,
            top_padding = top_padding,
            right_padding = right_padding,
            bottom_padding = bottom_padding,
            left_padding = left_padding,
            plain_text = plain_text
        ))
    _console.print(*renderables, sep = separator, end = end, **kwargs)

def input(
    text = "",
    color = "#ffffff",
    bold = False,
    italic = False,
    underline = False,
    strike = False,
    reverse = False
):
    return _console.input(_style(
        object = text,
        color = color,
        bold = bold,
        italic = italic,
        underline = underline,
        strike = strike,
        reverse = reverse,
        plain_text = True
    )).strip()

def clear_console(): os.system("cls" if os.name == "nt" else "clear")

def wait_for_key(
    text = "\nPulse cualquier tecla para continuar...",
    color = "#ffffff",
    bold = False,
    italic = False,
    underline = False,
    strike = False,
    reverse = False,
    alignment = "left",
    padding = 0,
    top_padding = None,
    right_padding = None,
    bottom_padding = None,
    left_padding = None
):
    print(
        text,
        color = color,
        bold = bold,
        italic = italic,
        underline = underline,
        strike = strike,
        reverse = reverse,
        alignment = alignment,
        padding = padding,
        top_padding = top_padding,
        right_padding = right_padding,
        bottom_padding = bottom_padding,
        left_padding = left_padding,
        end = ""
    )
    readchar.readkey()