import os
import gradio as gr
import pandas as pd
import requests
from urllib.parse import quote

leaderboard_url = os.getenv("LEADERBOARD_URL", "https://leaderboard.nexa4ai.com")

get_ranking_url = f"{leaderboard_url}/model/get-ranking-by-category"
get_models_url = f"{leaderboard_url}/model/get-models-by-category"
vote_url = f"{leaderboard_url}/model/vote"
submit_models_url = f"{leaderboard_url}/model/submit-models"
submit_category_url = f"{leaderboard_url}/model/submit-category"

def make_clickable_model(model_id):
    model_name_show = ' '.join(model_id.split('/')[1:])
    link = "https://huggingface.co/" + model_id
    return f'<a target="_blank" href="{link}" style="color: var(--link-text-color); text-decoration: underline;text-decoration-style: dotted;">{model_name_show}</a>'

def update_table(category):
    retries = 3
    while retries > 0:
        try:
            encoded_category = quote(category)
            url_with_params = f"{get_ranking_url}?category={encoded_category}"
            response = requests.get(url_with_params)
            if response.status_code == 200:
                ranking_data = response.json()["ranking"]
                api_model_data = {
                    "Model": [make_clickable_model(item["model_id"]) for item in ranking_data],
                    "Votes": [item["votes"] for item in ranking_data],
                    "Categories": [item["categories"] for item in ranking_data] if category == "all" else [category] * len(ranking_data)
                }
                api_df = pd.DataFrame(api_model_data)
                return api_df
            else:
                print(f"Failed to submit request: {response.text}")
                retries -= 1
        except requests.exceptions.RequestException as e:
            print(f"Error occurred while making request: {e}")
            retries -= 1
    return pd.DataFrame()


def get_vote_models(category):
    if not category:
        return []

    url_with_params = f"{get_models_url}?category={category}" 

    response = requests.get(url_with_params)

    if response.status_code == 200:
        models_data = response.json()
        return gr.CheckboxGroup(choices=models_data, label="Choose your options", interactive=True)
    else:
        print(f"Failed to get models: {response.text}")
        return []


def submit_vote(category, models):
    if not category or not models:
        return "All fields are required!"

    data = {
        "category": category,
        "model_ids": models
    }
    
    response = requests.post(vote_url, json=data)
    
    if response.status_code == 200:
        return f"Vote '{models}' submitted successfully!"
    else:
        return f"Failed to vote: {response.text}"


def submit_model(category, customize_category, model_id):
    if not model_id:
        return "All fields are required!"
    if not category or not customize_category:
        return "Please choose a category or customize your own category!"

    selected_category = category

    if customize_category:
        category_data = {
            "category": customize_category
        }
        response = requests.post(submit_category_url, json=category_data)
        if response.status_code != 200:
            return f"Failed to submit category: {response.text}"
        selected_category = customize_category

    data = {
        "model_id": model_id,
        "categories": [selected_category]
    }

    response = requests.post(submit_models_url, json=data)
    if response.status_code == 200:
        return "Your request has been submitted successfully. We will notify you by email once processing is complete."
    else:
        return f"Failed to submit request: {response.text}"

def update_dropdown(customize_category, category):
    if customize_category:  
        return "", gr.update(value="") 
    return category, gr.update() 

theme = gr.themes.Soft()

with gr.Blocks(theme=theme) as app:
    with gr.Tabs():
        with gr.TabItem("Table"):       
            category = gr.Dropdown(
                choices=["all", "Art & Design", "Biology", "Physics", "Business", "Chemistry", "Economics", "Philosophy", "History", "Culture", "Computer Science", "Math", "Education", "Health", "Law", "Engineering", "Coding", "Science", "Other"],
                label="Select Category",
                value="all"
            )
            
            initial_data = update_table("all")
            table = gr.Dataframe(
                headers=["Model", "Votes", "Categories"],
                datatype=["markdown", "number", "str"],
                value=initial_data,
                col_count=(3, "fixed"),
                height=600
            )
            app.load(lambda: update_table("all"), outputs=table)
            category.change(update_table, inputs=category, outputs=table)
   
        with gr.TabItem("Vote"):
            category = gr.Dropdown(
                choices=["Art & Design", "Biology", "Physics", "Business", "Chemistry", "Economics", "Philosophy", "History", "Culture", "Computer Science", "Math", "Education", "Health", "Law", "Engineering", "Coding", "Science", "Other"], 
                label="Select Category"
            )

            cbg = gr.CheckboxGroup(choices=[], label="Choose your options",interactive=True)
            submit_button = gr.Button("Submit Vote")
            submit_result = gr.Markdown()

            category.change(get_vote_models, inputs=category, outputs=cbg) 

            submit_button.click(fn=submit_vote, inputs=[category, cbg], outputs=submit_result)

        
        with gr.TabItem("Submit Model"):
            category = gr.Dropdown(choices=["Art & Design", "Biology", "Physics", "Business", "Chemistry", "Economics", "Philosophy", "History", "Culture", "Computer Science", "Math", "Education", "Health", "Law", "Engineering", "Coding", "Science", "Other"], label="Select Category")
            customize_category = gr.Textbox(label="Customize category", placeholder="Can't find your category? Enter your own.")
            model_id = gr.Textbox(label="Hub Model ID", placeholder="Submit model id")
            submit_model_button = gr.Button("Submit Model")
            submit_model_result = gr.Markdown()
            customize_category.change(fn=update_dropdown, inputs=[customize_category, category], outputs=[category])
            submit_model_button.click(fn=submit_model, inputs=[category, customize_category, model_id], outputs=submit_model_result)

app.launch(share=True)