import pandas as pd
import streamlit as st
import streamlit.components.v1 as components
from transformers import *
from carga_articulos import cargar_articulos
from preprocesamiento_articulos import limpieza_articulos
from entrenamiento_modelo import term_document_matrix, tf_idf_score
from resultados_consulta import resultados_consulta, detalles_resultados
import tensorflow as tf
import tensorflow.python.ops.numpy_ops.np_config as np_config
from math import ceil


def split_frame(input_df, rows):
    df=[]
    for i in range(0, len(input_df), rows):
        df.append(input_df.iloc[i : i + rows, :])
    return df

def paginar_frame(df):
     N_cards_per_row = 1
     for n_row, row in df.reset_index().iterrows():
        i = n_row%N_cards_per_row
        if i==0:
            st.write("---")
            cols = st.columns(N_cards_per_row, gap="large")
        # draw the card
        with cols[n_row%N_cards_per_row]:
            if 'answer' in row:
                if (row['answer']):
                    st.info(row['answer'])
            st.caption(f"{row['feed'].strip()} - {row['seccion'].strip()} - {row['fecha'].strip()} ")
            st.markdown(f"**{row['titulo'].strip()}**")
            st.markdown(f"{row['resumen'].strip()}")
            st.markdown(f"{row['link']}")
            
def crear_indice():
    df=cargar_articulos()
    vocab = limpieza_articulos(df)

    td_matrix=term_document_matrix(df, vocab, 'ID', 'titulo')
    td_idf_matrix=tf_idf_score(td_matrix, df.ID.values)

    td_idf_matrix.to_csv('articulos_indexados.csv') 

def load_qa_model():

    tokenizer = AutoTokenizer.from_pretrained('dccuchile/bert-base-spanish-wwm-cased', use_fast="false")
    model = TFAutoModelForQuestionAnswering.from_pretrained("Lisibonny/modelo_qa_beto_squad_es_5000")
    return tokenizer, model

# 4. Use streamlit to create a web app
def main():

    #crear_indice() 

    st.set_page_config(page_title="Buscador de noticias periodicos dominicanos", page_icon="📰", layout="centered")
    st.image('repartidor_periodicos.jpeg', width=150)
    st.header('El Repartidor Dominicano')

    
    # Sidebar
    st.sidebar.header("Acerca De")
    st.sidebar.markdown(
        "El Repartidor Dominicano es un sistema de recuperación de información desde periódicos dominicanos que usa técnicas de aprendizaje automático."
    )
    st.sidebar.markdown("Desarrollado por [Lisibonny Beato-Castro](https://scholar.google.com/citations?user=KSzjfeUAAAAJ&hl=es&oi=ao)")
    
    st.sidebar.header("Artículos Indexados")
    st.sidebar.markdown(
        """
    Los artículos noticiosos indexados son descargados de los feeds RSS de varios periódicos dominicanos.
    """
    )
    
    st.sidebar.header("Aviso Legal Sobre Uso de Datos")
    st.sidebar.markdown(
        """
        El uso de los artículos en este sitio tiene fines no comerciales, respetando los derechos de autor. Implementamos las mejores prácticas para el uso de RSS, tal y como son recomendadas por el Berkman Klein Center for Internet & Society de la Universidad de Harvard.
        
        Si quieres saber más acerca de los feeds RSS o de las mejores prácticas para el uso de RSS, haz clic en los siguientes enlaces:
        
        - [RSS](https://es.wikipedia.org/wiki/RSS)
        - [Uso legal de feeds RSS](https://cyber.harvard.edu/publications/2010/news_aggregator_legal_implications_best_practices)
        """
    )

    st.sidebar.header("¡Cómprame un Café!")
    st.sidebar.markdown("Si te gusta este sitio y quieres darme las gracias o animarme a hacer más, puedes hacer una pequeña donación.")
    with st.sidebar:
        components.html(
                """ 
                <div id="donate-button-container">
                <div id="donate-button"></div>
                <script src="https://www.paypalobjects.com/donate/sdk/donate-sdk.js" charset="UTF-8"></script>
                <script>
                PayPal.Donation.Button({
                env:'production',
                hosted_button_id:'VK5ZAB52ZYDNA',
                image: {
                src:'https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif',
                alt:'Dona con el botón de PayPal',
                title:'PayPal - ¡La forma más fácil y segura de pagar en línea!',
                }
                }).render('#donate-button');
                </script>
                </div>
                """
        )

    df=cargar_articulos()
    articulos_indexados = pd.read_csv('articulos_indexados.csv')
    articulos_indexados = articulos_indexados.set_index('Unnamed: 0')
    tokenizer, qa_model = load_qa_model()
    

    query = st.text_input(
        "Escribe tus términos de búsqueda o haz una pregunta terminando con el caracter ?:"
    )

    if query:

        # Si se especifico una pregunta 
        if ('?' in query):
           st.write("Contestando a: ", query)
           # Verificando cada resumen de los articulos como contexto a la pregunta 
           cantidad_respuestas = 0 
           lista_noticias_respuestas = [] 
           df_answer=df
           df_answer['answer']='' 
           progress_text = "Buscando respuestas. Por favor, espere."
           my_bar = st.progress(0, text=progress_text)
            
           for i in range(len(df_answer)):
                     
               text=df_answer.loc[i, "resumen"]
               inputs =  tokenizer(query, text, return_tensors='tf')
               outputs = qa_model(input_ids=inputs['input_ids'], attention_mask=inputs['attention_mask'])
               answer_start_index = int(tf.math.argmax(outputs.start_logits, axis=-1)[0])
               answer_end_index = int(tf.math.argmax(outputs.end_logits, axis=-1)[0])
               #answer_start_scores = tf.nn.softmax(outputs.start_logits)
               #answer_end_scores = tf.nn.softmax(outputs.end_logits)
               predict_answer_tokens = inputs.input_ids[0, answer_start_index : answer_end_index + 1] 
               answer=tokenizer.decode(predict_answer_tokens) 


               if (len(answer)>0):
               
                   #answer_start_scores= tf.math.reduce_sum(answer_start_scores)
                   #answer_end_scores= tf.math.reduce_sum(answer_end_scores)
                   #score = answer_start_scores*answer_end_scores
                   #st.write(f'Aqui {answer_start_scores}' )
                   #st.write(answer_end_scores)
                   cantidad_respuestas = cantidad_respuestas + 1
                   df_answer.loc[i, "answer"] = answer
                   lista_noticias_respuestas.append(df_answer.loc[i].to_frame().T)

               # Barra de progreso
               my_bar.progress(i + 1, text=progress_text)

           my_bar.empty()
            
           df_noticias_respuestas=pd.concat(lista_noticias_respuestas)
           batch_size = 5
           pages = split_frame(df_noticias_respuestas, batch_size)
           top_menu = st.columns(3)
                
           pagination = st.container()
            
           bottom_menu = st.columns((3))

           with pagination: 
            
               with bottom_menu[2]:
                   total_pages = (ceil(cantidad_respuestas / batch_size) if ceil(cantidad_respuestas / batch_size) > 0 else 1)
                   current_page = st.number_input("Página", min_value=1, max_value=total_pages, step=1)  
                    
               with bottom_menu[1]:
                   st.write("---")
                   st.markdown(f"Página **{current_page}** de **{total_pages}** ") 
                    
               with top_menu[0]:
                   pagina_res_fin= batch_size*current_page if batch_size*current_page <= cantidad_respuestas else cantidad_respuestas
                   st.markdown(f"Respuestas **{(current_page*batch_size)-batch_size+1}-{pagina_res_fin}**  de  **{cantidad_respuestas}** ") 
                        
               paginar_frame(pages[current_page - 1]) 
                  
                   

        # Si se especificaron keywords
        else:    

            st.write("Buscando: ", query)
            result = resultados_consulta(df,articulos_indexados, query)

            if result.empty:
                st.info("No se encontraron artículos para la búsqueda solicitada")

            else:
            
                df_results=detalles_resultados(df,result)
                cantidad_resultados=len(df_results)
                batch_size = 5
                pages = split_frame(df_results, batch_size)
                top_menu = st.columns(3)
                    
                pagination = st.container()
                
                
                bottom_menu = st.columns((3))
            
                
                    
                with bottom_menu[2]:
                    total_pages = (ceil(cantidad_resultados / batch_size) if ceil(cantidad_resultados / batch_size) > 0 else 1)
                    current_page = st.number_input("Página", min_value=1, max_value=total_pages, step=1)  
                    
                with bottom_menu[1]:
                    st.write("---")
                    st.markdown(f"Página **{current_page}** de **{total_pages}** ") 
                    
                with top_menu[0]:
                    pagina_res_fin= batch_size*current_page if batch_size*current_page <= cantidad_resultados else cantidad_resultados
                    st.markdown(f"Artículos **{(current_page*batch_size)-batch_size+1}-{pagina_res_fin}**  de  **{cantidad_resultados}** ") 
                
                with pagination:        
                
                    paginar_frame(pages[current_page - 1])
                
                
                        
if __name__ == "__main__": 
    main()