import gradio as gr
import requests
from datetime import datetime, timezone

API_URL = "https://huggingface.co/api/daily_papers"

class PaperManager:
    def __init__(self, papers_per_page=30):
        self.papers_per_page = papers_per_page
        self.current_page = 1
        self.papers = []
        self.total_pages = 1

    def fetch_papers(self):
        try:
            response = requests.get(f"{API_URL}?limit=100")
            response.raise_for_status()
            data = response.json()

            # Sort papers by 'publishedAt' descending, then by 'upvotes' descending
            self.papers = sorted(
                data,
                key=lambda x: (
                    datetime.fromisoformat(
                        x.get('publishedAt', datetime.now(timezone.utc).isoformat()).replace('Z', '+00:00')
                    ),
                    x.get('paper', {}).get('upvotes', 0)
                ),
                reverse=True
            )

            self.total_pages = max((len(self.papers) + self.papers_per_page - 1) // self.papers_per_page, 1)
            self.current_page = 1
            return True
        except requests.RequestException as e:
            print(f"Error fetching papers: {e}")
            return False
        except Exception as e:
            print(f"Unexpected error: {e}")
            return False

    def format_paper(self, paper, rank):
        title = paper.get('title', 'No title')
        paper_id = paper.get('paper', {}).get('id', '')
        url = f"https://huggingface.co/papers/{paper_id}"
        authors = ', '.join([author.get('name', '') for author in paper.get('paper', {}).get('authors', [])]) or 'Unknown'
        upvotes = paper.get('paper', {}).get('upvotes', 0)
        comments = paper.get('numComments', 0)
        published_time = datetime.fromisoformat(
            paper.get('publishedAt', datetime.now(timezone.utc).isoformat()).replace('Z', '+00:00')
        )
        time_diff = datetime.now(timezone.utc) - published_time
        time_ago_days = time_diff.days
        time_ago = f"{time_ago_days} days ago" if time_ago_days > 0 else "today"

        return f"""
        <tr class="athing">
            <td align="right" valign="top" class="title"><span class="rank">{rank}.</span></td>
            <td valign="top" class="votelinks">
                <center><div class="votearrow"></div></center>
            </td>
            <td class="title">
                <a href="{url}" class="storylink" target="_blank">{title}</a>
            </td>
        </tr>
        <tr>
            <td colspan="2"></td>
            <td class="subtext">
                <span class="score">{upvotes} points</span> by {authors} | {time_ago} | <a href="#">{comments} comments</a>
            </td>
        </tr>
        <tr style="height:5px"></tr>
        """

    def render_papers(self):
        start = (self.current_page - 1) * self.papers_per_page
        end = start + self.papers_per_page
        current_papers = self.papers[start:end]

        if not current_papers:
            return "<div class='no-papers'>No papers available for this page.</div>"

        papers_html = "".join([self.format_paper(paper, idx + start + 1) for idx, paper in enumerate(current_papers)])
        return f"""
        <table border="0" cellpadding="0" cellspacing="0" class="itemlist">
            {papers_html}
        </table>
        """

    def next_page(self):
        if self.current_page < self.total_pages:
            self.current_page += 1
        return self.render_papers()

    def prev_page(self):
        if self.current_page > 1:
            self.current_page -= 1
        return self.render_papers()

paper_manager = PaperManager()

def initialize_app():
    if paper_manager.fetch_papers():
        return paper_manager.render_papers()
    else:
        return "<div class='no-papers'>Failed to fetch papers. Please try again later.</div>"

def refresh_papers():
    if paper_manager.fetch_papers():
        return paper_manager.render_papers()
    else:
        return "<div class='no-papers'>Failed to refresh papers. Please try again later.</div>"

css = """
body {
    background-color: white;
    font-family: Verdana, Geneva, sans-serif;
    margin: 0;
    padding: 0;
}

a {
    color: #0000ff;
    text-decoration: none;
}

a:visited {
    color: #551A8B;
}

.container {
    width: 85%;
    margin: auto;
}

table {
    width: 100%;
}

.title {
    background-color: #ff6600;
    padding: 2px 10px;
}

.title a {
    color: black;
    font-weight: bold;
    font-size: 14pt;
}

.itemlist .athing {
    background-color: #f6f6ef;
}

.rank {
    font-size: 14pt;
    color: #828282;
    padding-right: 5px;
}

.votelinks {
    width: 10px;
}

.votearrow {
    width: 0; 
    height: 0; 
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-bottom: 10px solid #828282;
    margin: auto;
}

.storylink {
    font-size: 10pt;
}

.subtext {
    font-size: 8pt;
    color: #828282;
    padding-left: 40px;
}

.subtext a {
    color: #828282;
    text-decoration: none;
}

.more-link button {
    background: none;
    border: none;
    color: #0000ff;
    text-decoration: underline;
    cursor: pointer;
    font-size: 10pt;
    padding: 0;
}

.no-papers {
    text-align: center;
    color: #828282;
    padding: 1rem;
    font-size: 14pt;
}

@media (max-width: 640px) {
    .title a {
        font-size: 12pt;
    }

    .storylink {
        font-size: 9pt;
    }

    .subtext {
        font-size: 7pt;
    }
}
"""

demo = gr.Blocks(css=css)

with demo:
    with gr.Column(elem_classes=["container"]):
        # Header with Refresh Button
        gr.HTML("""
        <table border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ff6600">
            <tr>
                <td style="padding: 8px;">
                    <span class="pagetop">
                        <b class="hnname"><a href="#" style="color: black; text-decoration: none;">Daily Papers</a></b>
                    </span>
                </td>
                <td align="right" style="padding: 8px;">
                    <button id="refresh-button">Refresh</button>
                </td>
            </tr>
        </table>
        """)
        # Paper list
        paper_list = gr.HTML()
        # Navigation Buttons
        with gr.Row():
            prev_button = gr.Button("Prev")
            next_button = gr.Button("Next")
        # "More" Button Styled as Link
        with gr.Row():
            more_button = gr.Button("More", elem_classes="more-link")

    # Load papers on app start
    demo.load(initialize_app, outputs=[paper_list])

    # Button clicks
    prev_button.click(paper_manager.prev_page, outputs=[paper_list])
    next_button.click(paper_manager.next_page, outputs=[paper_list])
    more_button.click(paper_manager.next_page, outputs=[paper_list])
    # Bind the refresh button
    refresh_button = gr.Button(visible=False, elem_id="refresh-hidden")
    refresh_button.click(refresh_papers, outputs=[paper_list])

    # JavaScript to bind the click event to the refresh button
    demo.load(None, _js="""
    function() {
        document.getElementById('refresh-button').addEventListener('click', function() {
            document.querySelector('button#refresh-hidden').click();
        });
    }
    """)

demo.launch()