from datetime import datetime

import discord

AOC_DAY_AND_STAR_TEMPLATE = "{rank: >4} | {name:25.25} | {completion_time: >10}"


class AoCDropdownView(discord.ui.View):
    """Interactive view to filter AoC stats by Day and Star."""

    def __init__(self, original_author: discord.Member, day_and_star_data: dict[str: dict], maximum_scorers: int):
        super().__init__()
        self.day = 0
        self.star = 0
        self.data = day_and_star_data
        self.maximum_scorers = maximum_scorers
        self.original_author = original_author

    def generate_output(self) -> str:
        """Generates a formatted codeblock with AoC statistics based on the currently selected day and star."""
        header = AOC_DAY_AND_STAR_TEMPLATE.format(
            rank="Rank",
            name="Name", completion_time="Completion time (UTC)"
        )
        lines = [f"{header}\n{'-' * (len(header) + 2)}"]

        for rank, scorer in enumerate(self.data[f"{self.day}-{self.star}"][:self.maximum_scorers]):
            time_data = datetime.fromtimestamp(scorer['completion_time']).strftime("%I:%M:%S %p")
            lines.append(AOC_DAY_AND_STAR_TEMPLATE.format(
                datastamp="",
                rank=rank + 1,
                name=scorer['member_name'],
                completion_time=time_data)
            )
        joined_lines = "\n".join(lines)
        return f"Statistics for Day: {self.day}, Star: {self.star}.\n ```\n{joined_lines}\n```"

    async def interaction_check(self, interaction: discord.Interaction) -> bool:
        """Global check to ensure that the interacting user is the user who invoked the command originally."""
        return interaction.user == self.original_author

    @discord.ui.select(
        placeholder="Day",
        options=[discord.SelectOption(label=str(i)) for i in range(1, 26)],
        custom_id="day_select"
    )
    async def day_select(self, select: discord.ui.Select, interaction: discord.Interaction) -> None:
        """Dropdown to choose a Day of the AoC."""
        self.day = select.values[0]

    @discord.ui.select(
        placeholder="Star",
        options=[discord.SelectOption(label=str(i)) for i in range(1, 3)],
        custom_id="star_select"
    )
    async def star_select(self, select: discord.ui.Select, interaction: discord.Interaction) -> None:
        """Dropdown to choose either the first or the second star."""
        self.star = select.values[0]

    @discord.ui.button(label="Fetch", style=discord.ButtonStyle.blurple)
    async def fetch(self, button: discord.ui.Button, interaction: discord.Interaction) -> None:
        """Button that fetches the statistics based on the dropdown values."""
        if self.day == 0 or self.star == 0:
            await interaction.response.send_message(
                "You have to select a value from both of the dropdowns!",
                ephemeral=True
            )
        else:
            await interaction.response.edit_message(content=self.generate_output())
            self.day = 0
            self.star = 0

from datetime import datetime

import discord

AOC_DAY_AND_STAR_TEMPLATE = "{rank: >4} | {name:25.25} | {completion_time: >10}"


class AoCDropdownView(discord.ui.View):
    """Interactive view to filter AoC stats by Day and Star."""

    def __init__(self, original_author: discord.Member, day_and_star_data: dict[str: dict], maximum_scorers: int):
        super().__init__()
        self.day = 0
        self.star = 0
        self.data = day_and_star_data
        self.maximum_scorers = maximum_scorers
        self.original_author = original_author

    def generate_output(self) -> str:
        """Generates a formatted codeblock with AoC statistics based on the currently selected day and star."""
        header = AOC_DAY_AND_STAR_TEMPLATE.format(
            rank="Rank",
            name="Name", completion_time="Completion time (UTC)"
        )
        lines = [f"{header}\n{'-' * (len(header) + 2)}"]

        for rank, scorer in enumerate(self.data[f"{self.day}-{self.star}"][:self.maximum_scorers]):
            time_data = datetime.fromtimestamp(scorer['completion_time']).strftime("%I:%M:%S %p")
            lines.append(AOC_DAY_AND_STAR_TEMPLATE.format(
                datastamp="",
                rank=rank + 1,
                name=scorer['member_name'],
                completion_time=time_data)
            )
        joined_lines = "\n".join(lines)
        return f"Statistics for Day: {self.day}, Star: {self.star}.\n ```\n{joined_lines}\n```"

    async def interaction_check(self, interaction: discord.Interaction) -> bool:
        """Global check to ensure that the interacting user is the user who invoked the command originally."""
        return interaction.user == self.original_author

    @discord.ui.select(
        placeholder="Day",
        options=[discord.SelectOption(label=str(i)) for i in range(1, 26)],
        custom_id="day_select"
    )
    async def day_select(self, select: discord.ui.Select, interaction: discord.Interaction) -> None:
        """Dropdown to choose a Day of the AoC."""
        self.day = select.values[0]

    @discord.ui.select(
        placeholder="Star",
        options=[discord.SelectOption(label=str(i)) for i in range(1, 3)],
        custom_id="star_select"
    )
    async def star_select(self, select: discord.ui.Select, interaction: discord.Interaction) -> None:
        """Dropdown to choose either the first or the second star."""
        self.star = select.values[0]

    @discord.ui.button(label="Fetch", style=discord.ButtonStyle.blurple)
    async def fetch(self, button: discord.ui.Button, interaction: discord.Interaction) -> None:
        """Button that fetches the statistics based on the dropdown values."""
        if self.day == 0 or self.star == 0:
            await interaction.response.send_message(
                "You have to select a value from both of the dropdowns!",
                ephemeral=True
            )
        else:
            await interaction.response.edit_message(content=self.generate_output())
            self.day = 0
            self.star = 0

Interactive view to filter AoC stats by Day and Star. Generates a formatted codeblock with AoC statistics based on the currently selected day and star. Global check to ensure that the interacting user is the user who invoked the command originally. Dropdown to choose a Day of the AoC. Dropdown to choose either the first or the second star. Button that fetches the statistics based on the dropdown values.