import os
import shutil
import re
import yaml
import qrcode
from qrcode.image.styledpil import StyledPilImage
from qrcode.image.styles.moduledrawers import RoundedModuleDrawer, GappedSquareModuleDrawer
from qrcode.image.styles.colormasks import SolidFillColorMask
import PIL
from PIL import Image, ImageDraw, ImageFont

# ============================================ FUNÇÕES ==================================================
def extract_qrcode_info(filename, quantidade, pasta, config):

    cor = config['cor']
    site_de_publicacao = config['site_de_publicacao']
    livro_url = config['livro_url']

    ark = None

    if 'ark' in config:
        ark = 'https://n2t.net/'+config['ark']

    with open(filename, 'r', encoding='utf-8') as file:
        markdown_text = file.read()

    # Definindo o padrão de expressão regular para capturar o conteúdo entre ::: { e }
    pattern = r':::\s*\{([^{}]*)\}\s*(.*?)\s*:::'
    matches = re.findall(pattern, markdown_text, re.DOTALL)

    # Loop pelas correspondências encontradas
    for match in matches:
        div_attributes = match[0].strip()
        content = match[1].strip()


        # Verifica se a div tem a classe .qrcode
        if '.qrcode' in div_attributes:

            quantidade += 1

            print("------------ INICIO -------------", quantidade)

            print("Atributos:", div_attributes)
            print("Conteúdo:", content)

            # Verifica se a div tem a classe .content-visible
            content_visible = '.content-visible' in div_attributes

            if content_visible:
                print("Tem a classe .content-visible")
                # Extrai o valor do atributo when-format
                when_format_match = re.search(r'when-format="([^"]+)"', div_attributes)
                print("whenformat: ", when_format_match)

                if when_format_match:
                    start_index = when_format_match.start()
                    end_index = when_format_match.end()
                    when_format_text = div_attributes[start_index:end_index]
                    print("FORMA: ",when_format_text) 

            else:
                print("Não tem a classe .content-visible")

            qrcor_attr = re.search(r'qrcor="([^"]+)"', div_attributes)

            if qrcor_attr:
                start_index = qrcor_attr.start()
                end_index = qrcor_attr.end()
                qrcor_text = div_attributes[start_index:end_index]
                
                padrao = r'"(.*?)"'
                resultados = re.findall(padrao, qrcor_text)

                print("RESULTADOS: ",resultados)

                if resultados[0] == "0":
                    qrcor = False
                else:
                    qrcor = True

            else:
                qrcor = True

        # ================================ GERAR QRCODE ================================

            if not hasattr(PIL.Image, 'Resampling'):
                PIL.Image.Resampling = PIL.Image

            hex_color = cor
            rgb_color = hex_to_rgb(hex_color)


            qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H)

# ++++++++++++++++++++ DEFININDO OS LINKS DOS QR CODES +++++++++++++++++++++++++++++++++++++++++++++

            # define qual será a base para os links internos no qrcode +
            if ark is not None:
                base = ark
            else:
                base = site_de_publicacao+'/'+livro_url

            # verifica se o link é externo ou interno
            if not 'http' in content and '#' in content:
                
                #link interno

                # Verifica se é para o um capítulo diferente do avaliado. Se tiver a barra, entao é para outro capítulo

                if '/' in content:
                    content = base +'/'+ content
                else:
                    cap = filename.split('.')[0]
                    content = base +'/'+ cap +'/'+ content


            qr.add_data(content)

            qr_inner_eyes_img = qr.make_image(image_factory=StyledPilImage,
                                        eye_drawer=RoundedModuleDrawer(radius_ratio=1),
                                        color_mask=SolidFillColorMask(front_color=(rgb_color['red'], rgb_color['green'], rgb_color['blue'])))

            qr_outer_eyes_img = qr.make_image(image_factory=StyledPilImage,
                                        eye_drawer=RoundedModuleDrawer(radius_ratio=1))    

            qr_img = qr.make_image(image_factory=StyledPilImage,
                                    module_drawer=GappedSquareModuleDrawer(),
                                embeded_image_path="editora/logo_roxo.png")

            inner_eye_mask = style_inner_eyes(qr_img)
            outer_eye_mask = style_outer_eyes(qr_img)
            intermediate_img = Image.composite(qr_inner_eyes_img, qr_img, inner_eye_mask)
            final_image = Image.composite(qr_outer_eyes_img, intermediate_img, outer_eye_mask)

            final_image = final_image.convert('CMYK')

            # Verifica se tem que ser preto e branco
            if not qrcor:
                final_image = final_image.convert('L')
                final_image = final_image.convert('CMYK')

                # Separa os canais CMYK
                c, m, y, k = final_image.split()

                # Cria novos canais C, M e Y com todos os valores definidos como zero
                c_new = c.point(lambda x: 0)
                m_new = m.point(lambda x: 0)
                y_new = y.point(lambda x: 0)

                # Cria uma nova imagem CMYK com os canais ajustados e o canal K original
                final_image = Image.merge('CMYK', (c_new, m_new, y_new, k))

            arq = "qrcode_" + str(quantidade) + ".jpg"
            caminho_e_arq = os.path.join(pasta, arq)
            final_image.save(caminho_e_arq, quality=100)



            print("QRCOR: ",qrcor)

            print("------------ FIM -------------")

    return quantidade


def obter_capitulos(arquivo_yaml):
    
    with open(arquivo_yaml, 'r') as file:
        # Carrega o conteúdo do arquivo YAML
        conteudo = yaml.safe_load(file)
        # Verifica se a chave 'capítulos' está presente no YAML
        if 'capitulos' in conteudo:
            return conteudo['capitulos']
        else:
            print("A chave 'capítulos' não foi encontrada no YAML.")
            return None

# A ideia aqui é obter as configuracoes do qrcode bem como o identificador ark e o site para publicacao
def obter_metadados(arquivo_yaml):
    
    metadados = {}

    with open(arquivo_yaml, 'r') as file:
        # Carrega o conteúdo do arquivo YAML
        conteudo = yaml.safe_load(file)

        # Verifica se a chave 'capítulos' está presente no YAML
        if 'qrcode' in conteudo:
            metadados['cor'] = conteudo['qrcode']['cor']

        if 'site-de-publicacao' in conteudo:
            metadados['site_de_publicacao'] = conteudo['site-de-publicacao']

            metadados['livro_url'] = conteudo['pasta-livro-finalizado']['html']

    with open('_quarto-html.yml', 'r') as file:

        conteudo_1 = yaml.safe_load(file)

        if 'ark' in conteudo_1['moan-dados']:
             metadados['ark'] = conteudo_1['moan-dados']['ark']


    return metadados
        

        
            
def criar_ou_limpar_pasta(nome_pasta):
    # Verifica se o diretório já existe
    if os.path.exists(nome_pasta):
        # Remove todo o conteúdo da pasta
        for filename in os.listdir(nome_pasta):
            file_path = os.path.join(nome_pasta, filename)
            try:
                if os.path.isfile(file_path) or os.path.islink(file_path):
                    os.unlink(file_path)
                elif os.path.isdir(file_path):
                    shutil.rmtree(file_path)
            except Exception as e:
                print(f"Erro ao remover {file_path}: {e}")
    else:
        # Cria a pasta se não existir
        try:
            os.makedirs(nome_pasta)
        except OSError as e:
            print(f"Erro ao criar a pasta {nome_pasta}: {e}")


# ============================================ FUNÇÕES QRCODE ==================================================


def hex_to_rgb(hex_color):
    # Remover o '#' se presente
    hex_color = hex_color.lstrip('#')
    
    # Converter para valores RGB
    red = int(hex_color[0:2], 16)
    green = int(hex_color[2:4], 16)
    blue = int(hex_color[4:6], 16)
    
    # Retornar como um dicionário
    return {'red': red, 'green': green, 'blue': blue}

# Custom function for eye styling. These create the eye masks
def style_inner_eyes(img):
    img_size = img.size[0]
    eye_size = 70 # default
    quiet_zone = 40 # default
    mask = Image.new('L', img.size, 0)
    draw = ImageDraw.Draw(mask)
    draw.rectangle((60, 60, 90, 90), fill=255) #top left eye
    draw.rectangle((img_size-90, 60, img_size-60, 90), fill=255) #top right eye
    draw.rectangle((60, img_size-90, 90, img_size-60), fill=255) #bottom left eye
    return mask

def style_outer_eyes(img):
    img_size = img.size[0]
    eye_size = 70 # default
    quiet_zone = 40 # default
    mask = Image.new('L', img.size, 0)
    draw = ImageDraw.Draw(mask)
    draw.rectangle((40, 40, 110, 110), fill=255) #top left eye
    draw.rectangle((img_size-110, 40, img_size-40, 110), fill=255) #top right eye
    draw.rectangle((40, img_size-110, 110, img_size-40), fill=255) #bottom left eye
    draw.rectangle((60, 60, 90, 90), fill=0) #top left eye
    draw.rectangle((img_size-90, 60, img_size-60, 90), fill=0) #top right eye
    draw.rectangle((60, img_size-90, 90, img_size-60), fill=0) #bottom left eye 
    return mask  
# ============================================ FIM DAS FUNÇÕES QRCODE ==================================================



# ============================================ FIM DAS FUNÇÕES GERAIS==================================================       
  

contador = 0

# Caminho para o arquivo YAML
caminho_arquivo = '_moan-config.yml'

# Obtém os capítulos do arquivo YAML
capitulos = obter_capitulos(caminho_arquivo)

# metadados qrcode
config = obter_metadados(caminho_arquivo)

pasta_qr = "qr_code"
criar_ou_limpar_pasta(pasta_qr)

if capitulos:
    for capitulo in capitulos:
        # Usando a função para extrair informações de um arquivo .qmd
        contador = extract_qrcode_info(capitulo, contador, pasta_qr,config)
        
else:
    print("Nenhum capítulo encontrado no arquivo YAML.")


# Aguardar entrada do usuário antes de fechar o terminal
input("Pressione Enter para fechar o terminal...")