import datetime
import os
import shutil

import gradio as gr
import requests

from utils import build_issue_dict
from utils import build_embeddings
from utils.defaults import OWNER, REPO
from utils.fetch import get_issues
from utils.find_similar_issues import get_similar_issues
from utils.update_stored_issues import update_issues


def get_query_issue_information(issue_no, token):
    headers = {
        "Accept": "application/vnd.github+json",
        "Authorization": f"{token}",
        "X-GitHub-Api-Version": "2022-11-28",
        "User-Agent": "amyeroberts",
    }
    request = requests.get(
        f"https://api.github.com/repos/{OWNER}/{REPO}/issues/{issue_no}",
        headers=headers,
    )
    if request.status_code != 200:
        raise ValueError(f"Request failed with status code {request.status_code} and message {request.text}")

    return request.json()


def run_find_similar_issues(token, n_issues, issue_no, query, issue_types):
    if issue_no == "":
        issue_no = None
    if query == "":
        query = None

    if len(issue_types) == 0:
        raise ValueError("At least one issue type must be selected")

    similar_issues = []
    similar_pulls = []
    if "Issue" in issue_types:
        similar_issues = get_similar_issues(issue_no=issue_no, query=query, token=token, top_k=n_issues, issue_type="issue")
    if "Pull Request" in issue_types:
        similar_pulls = get_similar_issues(issue_no=issue_no, query=query, token=token, top_k=n_issues, issue_type="pull")

    issues_html = [f"<a href='{issue['html_url']}' target='_blank'>#{issue['number']} - {issue['title']}</a>" for issue in similar_issues]
    issues_html = "<br>".join(issues_html)

    pulls_html = [f"<a href='{issue['html_url']}' target='_blank'>#{issue['number']} - {issue['title']}</a>" for issue in similar_pulls]
    pulls_html = "<br>".join(pulls_html)

    final = ""
    if len(issues_html) > 0:
        final += f"<h2>Issues</h2>{issues_html}"
    if len(pulls_html) > 0:
        final += f"<h2>Pull Requests</h2>{pulls_html}"

    # return issues_html
    return final


def update(token):
    # Archive the stored issues
    if os.path.exists("issues.json"):
        date_time = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
        shutil.copy("issues.json", f"{date_time}_issues.json")

    # Retrieve new issues
    get_issues(overwrite=False, update=True, output_filename="issues.json", token=token)
    # Update any issues that have been updated since the last update
    update_issues(token=token)
    # Update the dictionary of issues
    build_issue_dict.build_json_file("issues.json", "issues_dict.json")
    # Update the embeddings
    build_embeddings.embed_issues(
        input_filename="issues_dict.json",
        issue_type="issue",
        model_id="all-mpnet-base-v2",
        update=True
    )
    build_embeddings.embed_issues(
        input_filename="issues_dict.json",
        issue_type="pull",
        model_id="all-mpnet-base-v2",
        update=True
    )


with gr.Blocks(title="Github Bot") as demo:
    with gr.Tab("Find similar issues"):
        with gr.Row():
            gr.Markdown("## Query settings")
        with gr.Row():
            gr.Markdown("Configure the settings for the query. You can either search for similar issues to a given issue or search for issues based on a query.")
        with gr.Row():
            with gr.Column():
                gr.Markdown("Find similar issues to a given issue or query")
                issue_no = gr.Textbox(label="Github Issue", placeholder="Github issue you want to find similar issues to")
                query = gr.Textbox(label="Query", placeholder="Search for issues")
            with gr.Column():
                token = gr.Textbox(label="Github Token", placeholder="Your github token for authentication. This is not stored anywhere.")
                n_issues = gr.Slider(1, 50, value=5, step=1, label="Number of similar issues", info="Choose between 1 and 50")
                issue_types = gr.CheckboxGroup(["Issue", "Pull Request"], label="Issue types")

        with gr.Row():
                submit_button = gr.Button(value="Submit")

        with gr.Row():
            with gr.Row():
                issues_html = gr.HTML(label="Issue text", elem_id="issue_html")
                submit_button.click(run_find_similar_issues, outputs=[issues_html], inputs=[token, n_issues, issue_no, query, issue_types])

        with gr.Row():
            with gr.Column():
                gr.Markdown("Press `Update Button` to update the stored issues. This will take a few minutes.")
                update_button = gr.Button(value="Update issues")
                update_button.click(update, outputs=[], inputs=[token], trigger_mode="once")
            with gr.Column():
                pass

    with gr.Tab("Find maintainers to ping"):
        gr.Markdown("Find maintainers to ping for a given issue or pull request - DO NOT CURRENTLY HAVE FUNCTIONALITY")
        with gr.Row():
            issue = gr.Textbox(label="Github Issue / PR", placeholder="Issue or PR you want to find maintainers to ping for")
        with gr.Row():
            token = gr.Textbox(label="Github Token", placeholder="Your github token for authentication. This is not stored anywhere.")


if __name__ == "__main__":
    demo.launch()