from django import template
from django.utils.safestring import mark_safe
from django.utils.html import format_html

register = template.Library()

# =========================
# BLOCO: TAGS DE ESTRUTURA PRINCIPAL DO HEADER
# =========================

class SimpleBlockNode(template.Node):
    def __init__(self, nodelist, tag_name, default_classes, extra_classes_var=None):
        self.nodelist = nodelist
        self.tag_name = tag_name
        self.default_classes = default_classes
        self.extra_classes_var = extra_classes_var

    def render(self, context):
        content = self.nodelist.render(context)
        extra_classes = ''

        if self.extra_classes_var:
            try:
                resolved = template.Variable(self.extra_classes_var).resolve(context)
                extra_classes = f' {resolved}'
            except template.VariableDoesNotExist:
                extra_classes = f' {self.extra_classes_var}'

        if self.tag_name == "header":
            tag_open = f'<header class="{self.default_classes}{extra_classes}">'
            tag_inner_container = f'<div class="container-lg">{content}</div>'
            search_html = context.get('br_header_search_html', '')
            tag_close = '</header>'
            return format_html('{}{}{}{}', mark_safe(tag_open), mark_safe(tag_inner_container), mark_safe(search_html), mark_safe(tag_close))
        else:
            tag_open = f'<{self.tag_name} class="{self.default_classes}{extra_classes}">'
            tag_close = f'</{self.tag_name}>'
            return format_html('{}{}{}', mark_safe(tag_open), mark_safe(content), mark_safe(tag_close))

def create_simple_block(name, tag_name, default_classes):
    def tag_func(parser, token):
        bits = token.split_contents()
        extra_classes_var = None

        if len(bits) > 1:
            for bit in bits[1:]:
                if bit.startswith('class='):
                    extra_classes_var = bit.split('=')[1].strip('"\'')
        nodelist = parser.parse(['end_' + name])
        parser.delete_first_token()
        return SimpleBlockNode(nodelist, tag_name, default_classes, extra_classes_var)
    register.tag(name, tag_func)

# Header raiz e principais blocos
create_simple_block('br_header', 'header', 'br-header')           # Header principal
create_simple_block('br_header_top', 'div', 'header-top')         # Bloco superior do header
create_simple_block('br_header_bottom', 'div', 'header-bottom')   # Bloco inferior do header
create_simple_block('br_header_list', 'div', 'header')            # Lista de itens do header

# =========================
# BLOCO: TAGS DE TÍTULO E SUBTÍTULO
# =========================

class BrListTitleNode(template.Node):
    def __init__(self, nodelist, style=None):
        self.nodelist = nodelist
        self.style = style

    def render(self, context):
        content = self.nodelist.render(context)

        if self.style:
            try:
                style = template.Variable(self.style).resolve(context)
            except template.VariableDoesNotExist:
                style = self.style.strip('"\'')
        else:
            style = ""

        return format_html('<div class="title" style="{}">{}</div>', style, mark_safe(content))

@register.tag(name='br_list_title')
def do_br_list_title(parser, token):
    bits = token.split_contents()
    style = None

    for bit in bits[1:]:
        if bit.startswith("style="):
            style = bit.split("=", 1)[1]

    nodelist = parser.parse(('end_br_list_title',))
    parser.delete_first_token()

    return BrListTitleNode(nodelist, style=style)

class BrHeaderTitleNode(template.Node):
    def __init__(self, nodelist, style):
        self.nodelist = nodelist
        self.style = style

    def render(self, context):
        content = self.nodelist.render(context)
        style_attr = f' style="{self.style}"' if self.style else ''
        return mark_safe(f'<div class="header-title"{style_attr}>{content}</div>')

@register.tag(name='br_header_title')
def do_br_header_title(parser, token):
    bits = token.split_contents()
    style = ''
    if len(bits) > 1:
        for bit in bits[1:]:
            if bit.startswith('style='):
                style = bit.split('=', 1)[1].strip('"\'')
    nodelist = parser.parse(('end_br_header_title',))
    parser.delete_first_token()
    return BrHeaderTitleNode(nodelist, style)

class BrHeaderSubtitleNode(template.Node):
    def __init__(self, nodelist, style):
        self.nodelist = nodelist
        self.style = style

    def render(self, context):
        content = self.nodelist.render(context)
        style_attr = f' style="{self.style}"' if self.style else ''
        return mark_safe(f'<div class="header-subtitle"{style_attr}>{content}</div>')

@register.tag(name='br_header_subtitle')
def do_br_header_subtitle(parser, token):
    bits = token.split_contents()
    style = ''
    if len(bits) > 1:
        for bit in bits[1:]:
            if bit.startswith('style='):
                style = bit.split('=', 1)[1].strip('"\'')
    nodelist = parser.parse(('end_br_header_subtitle',))
    parser.delete_first_token()
    return BrHeaderSubtitleNode(nodelist, style)

# =========================
# BLOCO: TAGS DE MENU E AÇÕES
# =========================

class BrHeaderMenuNode(template.Node):
    def __init__(self, nodelist, icon_style=''):
        self.nodelist = nodelist
        self.icon_style = icon_style

    def render(self, context):
        content = self.nodelist.render(context)
        style_attr = f' style="{self.icon_style}"' if self.icon_style else ''
        return mark_safe(f'''
        <div class="header-menu">
            <div class="header-menu-trigger">
                <button class="br-button small circle" type="button" aria-label="Menu" data-toggle="menu" data-target="#main-navigation" id="navigation">
                    <i class="fas fa-bars" aria-hidden="true"{style_attr}></i>
                </button>
            </div>
            <div class="header-info">
                {content}
            </div>
        </div> 
        ''')

@register.tag(name='br_header_menu')
def do_br_header_menu(parser, token):
    bits = token.split_contents()
    icon_style = ''
    if len(bits) > 1:
        for bit in bits[1:]:
            if bit.startswith('icon_style='):
                icon_style = bit.split('=', 1)[1].strip('"\'')
    nodelist = parser.parse(('end_br_header_menu',))
    parser.delete_first_token()
    return BrHeaderMenuNode(nodelist, icon_style)

class ActionsNode(template.Node):
    def __init__(self, nodelist):
        self.nodelist = nodelist
    def render(self, context):
        content = self.nodelist.render(context)
        return format_html('<div class="header-actions">{}</div>', mark_safe(content))

@register.tag
def br_header_actions(parser, token):
    nodelist = parser.parse(['end_br_header_actions'])
    parser.delete_first_token()
    return ActionsNode(nodelist)

# =========================
# BLOCO: TAGS DE LOGO E AVATAR
# =========================

@register.simple_tag
def br_header_logo(src, alt, signature="", signature_style=""):
    """
    Renderiza o logo do header, podendo incluir assinatura customizada.
    """
    logo_html = format_html('<img src="{}" alt="{}" />', src, alt)
    style_attr = format_html(' style="{}"', signature_style) if signature_style else ''

    if signature:
        return format_html(
            '''<div class="header-logo">
                {}
                <span class="br-divider vertical"></span>
                <div class="header-sign"{}>{}</div>
            </div>''',
            logo_html,
            style_attr,
            mark_safe(signature)
        )
    else:
        return format_html('<div class="header-logo">{}</div>', logo_html)

@register.simple_tag
def br_header_avatar(icon=""):
    """
    Renderiza o avatar do usuário no header.
    """
    return format_html('<div class="header-avatar">{}</div>', mark_safe(icon))

# =========================
# BLOCO: DROPDOWN DE LINKS E FUNÇÕES
# =========================

class DropdownNode(template.Node):
    def __init__(self, nodelist, tag_name, class_name, icon_style):
        self.nodelist = nodelist
        self.tag_name = tag_name
        self.class_name = class_name
        self.icon_style = icon_style

    def render(self, context):
        content = self.nodelist.render(context)
        icon_style_attr = f' style="{self.icon_style}"' if self.icon_style else ''
        icon_class = 'fa-ellipsis-v' if 'links' in self.tag_name else 'fa-th'

        html = f'''
        <div class="{self.tag_name} {self.class_name}">
            <button class="br-button circle small" type="button" data-toggle="dropdown" aria-label="Abrir {self.tag_name.replace('-', ' ').title()}">
                <i class="fas {icon_class}" aria-hidden="true"{icon_style_attr}></i>
            </button>
            <div class="br-list">
                {content}
            </div>
        </div>
        '''
        if 'links' in self.tag_name:
            html += '<span class="br-divider vertical mx-half mx-sm-1"></span>'
        return mark_safe(html)

def dropdown_tag(name, tag_class):
    def tag_func(parser, token):
        bits = token.split_contents()
        class_name = "dropdown"
        icon_style = ""

        for bit in bits[1:]:
            if bit.startswith('class='):
                class_name = bit.split('=')[1].strip('"\'')
            elif bit.startswith('icon_style='):
                icon_style = bit.split('=')[1].strip('"\'')
        
        nodelist = parser.parse([f'end_{name}'])
        parser.delete_first_token()
        return DropdownNode(nodelist, tag_class, class_name, icon_style)

    register.tag(name, tag_func)

dropdown_tag('br_header_links', 'header-links')         # Dropdown de links rápidos
dropdown_tag('br_header_functions', 'header-functions') # Dropdown de funcionalidades

# =========================
# BLOCO: ITENS DE LISTA E FUNÇÕES
# =========================

class ItemNode(template.Node):
    """
    Renderiza um item de link dentro do header, como os links de acesso rápido.
    """
    def __init__(self, nodelist, href=None, extra_classes=None, style=None):
        self.nodelist = nodelist
        self.href = href
        self.extra_classes = extra_classes
        self.style = style

    def render(self, context):
        content = self.nodelist.render(context)

        # Resolve href
        if self.href:
            try:
                href = template.Variable(self.href).resolve(context)
            except template.VariableDoesNotExist:
                href = self.href.strip('"\'')
        else:
            href = "#"

        # Resolve extra_classes
        if self.extra_classes:
            try:
                extra_classes = template.Variable(self.extra_classes).resolve(context)
            except template.VariableDoesNotExist:
                extra_classes = self.extra_classes.strip('"\'')
        else:
            extra_classes = ''

        # Resolve style
        if self.style:
            try:
                style = template.Variable(self.style).resolve(context)
            except template.VariableDoesNotExist:
                style = self.style.strip('"\'')
        else:
            style = ''

        return format_html(
            '<a class="br-item {}" href="{}" style="{}">{}</a>',
            extra_classes, href, style, mark_safe(content)
        )

@register.tag
def br_item(parser, token):
    """
    Tag para criar um item de link no header.
    """
    bits = token.split_contents()
    tag_name = bits[0]

    href = None
    extra_classes = None
    style = None

    for bit in bits[1:]:
        if bit.startswith("href="):
            href = bit.split("=", 1)[1]
        elif bit.startswith("extra_classes="):
            extra_classes = bit.split("=", 1)[1]
        elif bit.startswith("style="):
            style = bit.split("=", 1)[1]

    nodelist = parser.parse(['end_br_item'])
    parser.delete_first_token()

    return ItemNode(nodelist, href=href, extra_classes=extra_classes, style=style)

class BrFunctionItemNode(template.Node):
    """
    Renderiza um item de funcionalidade no header, geralmente com ícone e label.
    """
    def __init__(self, icon_class, extra_classes=None, icon_style=None, label=None, label_style=None, aria_label=None):
        self.icon_class = icon_class
        self.extra_classes = extra_classes
        self.icon_style = icon_style
        self.label = label
        self.label_style = label_style
        self.aria_label = aria_label

    def render(self, context):
        def resolve(value):
            if value is None:
                return ''
            try:
                return template.Variable(value).resolve(context)
            except template.VariableDoesNotExist:
                return value.strip('"\'')
        
        icon_class = resolve(self.icon_class)
        extra_classes = resolve(self.extra_classes)
        icon_style = resolve(self.icon_style)
        label = resolve(self.label)
        label_style = resolve(self.label_style)
        aria_label = resolve(self.aria_label) or label

        return format_html(
            '''<div class="br-item {0}">
                <button class="br-button circle small" type="button" aria-label="{5}">
                    <i class="fas {1}" aria-hidden="true" style="{2}"></i>
                    <span class="text" style="{4}">{3}</span>
                </button>
            </div>''',
            extra_classes, icon_class, icon_style, label, label_style, aria_label
        )

@register.tag(name='br_function_item')
def do_br_function_item(parser, token):
    bits = token.split_contents()
    tag_name = bits[0]

    kwargs = {
        'icon_class': None,
        'extra_classes': None,
        'icon_style': None,
        'label': None,
        'label_style': None,
        'aria_label': None,
    }

    for bit in bits[1:]:
        if '=' in bit:
            key, value = bit.split('=', 1)
            if key in kwargs:
                kwargs[key] = value

    return BrFunctionItemNode(**kwargs)

# =========================
# BLOCO: TAGS DE BUSCA E LOGIN
# =========================

@register.simple_tag
def br_header_search_trigger(icon_style=""):
    """
    Botão para abrir a busca no header.
    """
    icon_style_attr = f' style="{icon_style}"' if icon_style else ""

    return mark_safe(f'''
    <div class="header-search-trigger">
        <button class="br-button circle" type="button" aria-label="Abrir Busca" data-toggle="search" data-target=".header-search">
            <i class="fas fa-search" aria-hidden="true"{icon_style_attr}></i>
        </button>
    </div>
    ''')

@register.simple_tag
def br_header_login():
    """
    Início do bloco de login no header.
    """
    return mark_safe('<div class="header-login">')

@register.simple_tag
def end_br_header_login():
    """
    Fim do bloco de login no header.
    """
    return mark_safe('</div>')

@register.simple_tag
def br_button():
    """
    Botão de login padrão.
    """
    return mark_safe('''
    <div class="header-sign-in">
        <button class="br-sign-in small" type="button" data-trigger="login">
            <i class="fas fa-user" aria-hidden="true"></i>
            <span class="d-sm-inline">Entrar</span>
        </button>
    </div>
    ''')

@register.simple_tag
def br_header_search(placeholder="", icon_style=""):
    """
    Campo de busca do header.
    """
    icon_style_attr = f' style="{icon_style}"' if icon_style else ""

    return mark_safe(f'''
    <div class="header-search">
        <div class="br-input has-icon">
            <label for="searchbox-114">Texto da pesquisa</label>
            <input id="searchbox-114" type="text" placeholder="{placeholder}"/>
            <button class="br-button circle small" type="button" aria-label="Pesquisar">
                <i class="fas fa-search" aria-hidden="true"></i>
            </button>
        </div>
        <button class="br-button circle search-close ml-1" type="button" aria-label="Fechar Busca" data-dismiss="search">
            <i class="fas fa-times" aria-hidden="true"{icon_style_attr}></i>
        </button>
    </div>
    ''')
