import os
import requests
from datetime import datetime

import gradio as gr
from gradio import components

import openai
from langchain_openai import ChatOpenAI
from langchain.chains.summarize import load_summarize_chain
from langchain.docstore.document import Document

def comment_datetime(comment_json):
    dt = datetime.fromisoformat(comment_json["created_at"][:-1])
    return comment_json["user"]["login"] + " commented on " + dt.strftime("%b %d, %Y") + ":"

str_format = """
{author}\n
{comment}
""".strip()

def get_comments(url):
    response = requests.get(url, headers=None)
    json_content = response.json()
    comments = "<|endoftext|>".join([str_format.format(author=comment_datetime(x).strip(), comment=x["body"].strip()) for x in json_content])

    return comments


template = """
### ISSUE #{issue_num}\n
### TITLE: {title}\n
### URL: {html_url}\n
### LABELS: {labels}\n
### BODY:\n
{body}\n
### COMMENTS:\n
{comments}\n
""".strip()

def get_full_context(row):
    labels = row["labels"].split("<|endoftext|>")
    comments = row["comments"].replace("<|endoftext|>", "\n\n")
    context = template.format(
        issue_num=row["issue_num"],
        url=row["url"],
        comments_url=row["comments_url"],
        html_url=row["html_url"],
        title=row["title"],
        labels=labels,
        body=row["body"],
        comments=comments
    )

    return context


def get_issue_info(url):
    url_items = url.split("/")
    url_api = "https://api.github.com/repos/{}/{}/issues/{}".format(url_items[-4], url_items[-3], url_items[-1])
    headers = {"Authorization": f"token {os.getenv('GITHUB_TOKEN')}"}
    response = requests.get(url_api, headers=None)
    issue = response.json()
    issue_short = {k: v for k, v in issue.items() if k in ["id", "url", "comments_url", "html_url", "title", "body"]}
    issue_short["labels"] = "<|endoftext|>".join([x["name"] for x in issue["labels"]])
    issue_short["issue_num"] = issue["number"]
    issue_short["comment_count"] = issue["comments"]

    # get comments
    issue_short["comments"] = get_comments(issue_short["comments_url"])

    # get context
    context = get_full_context(issue_short)
    
    return context
    

def init_chain(openai_api_key):
    llm = ChatOpenAI(
        model_name="gpt-4o",
        temperature=0.0,
        openai_api_key=openai_api_key
    )
    
    chain = load_summarize_chain(llm, chain_type="stuff")

    return chain


def get_summary(text, chain):
    doc = Document(page_content=text)
    summary = chain.invoke([doc])["output_text"].strip()

    return summary


template_output = """
## SUMMARY 📝
### {summary}
***
## Source 👾
{context}
""".strip()

def run_all(openai_api_key, url):
    try:
        context = get_issue_info(url)
    except (IndexError, KeyError) as error:
        return "## Invalid Github Issue URL.\n ## See examples below for reference."
    
    try:
        chain = init_chain(openai_api_key)
        summary = get_summary(context, chain)
        print(summary)
        return template_output.format(summary=summary, context=context)
    except (ValueError, openai.AuthenticationError) as error:
        return "## Invalid OpenAI API key provided."
    
html = """
<h1 style='text-align: center;'>GitHub Issue Summarizer</h1>
<img src="https://octodex.github.com/images/Professortocat_v2.png" width=100 height=100 style="display: block; margin: 0 auto;">
 """.strip()

examples = [
    [None, "https://github.com/rust-lang/rust/issues/97362"],
    [None, "https://github.com/rust-lang/rust/issues/83788"],
    [None, "https://github.com/langchain-ai/langchain/issues/9733"],
    [None, "https://github.com/huggingface/transformers/issues/25720"]
]

with gr.Blocks() as demo:
    with gr.Row():
        gr.HTML(html)

    with gr.Row():
        with gr.Column():
            with gr.Row():
                textbox_api_key = components.Textbox(placeholder="sk-...", label="OpenAI API Key", value=None, type="password")
            with gr.Row():
                textbox = gr.Textbox(label="Type a GitHub Issue URL:", placeholder="https://github.com/rust-lang/rust/issues/97362", lines=1)
            with gr.Row():
                summarize = gr.Button("Summarize", variant="primary")
                clear_button = gr.ClearButton()
            with gr.Row():
                gr.Examples(examples=examples, inputs=[textbox_api_key, textbox])
        with gr.Column(scale=1, min_width=1000):
            summary = gr.Markdown(value="Summary")
    summarize.click(run_all, [textbox_api_key, textbox], outputs=summary)
    clear_button.click(fn=lambda: [None, None, "Summary"], outputs=[textbox_api_key, textbox, summary])

demo.launch()