# flake8: noqa: E501
"""
Generates an HTML file to visualize the parsed data.
"""

import json
import os
from typing import Any, Dict, List, Union

from waybacktweets.utils import timestamp_parser


class HTMLTweetsVisualizer:
    """
    Class responsible for generating an HTML file to visualize the parsed data.

    Args:
        username (str): The username associated with the tweets.
        json_file_path (Union[str, List[str]]): The path of the JSON file or the JSON data itself.
        html_file_path (str, optional): The path where the HTML file will be saved.
    """

    def __init__(
        self,
        username: str,
        json_file_path: Union[str, List[str]],
        html_file_path: str = None,
    ):
        self.username = username
        self.json_file_path = self._json_loader(json_file_path)
        self.html_file_path = html_file_path

    @staticmethod
    def _json_loader(json_file_path: Union[str, List[str]]) -> List[Dict[str, Any]]:
        """
        Reads and loads JSON data from a specified file path or JSON string.

        Args:
            json_file_path (Union[str, List[str]]): The path of the JSON file or the JSON data itself.

        Returns:
            The content of the JSON file or data.
        """
        if os.path.isfile(json_file_path):
            with open(json_file_path, "r", encoding="utf-8") as f:
                return json.load(f)

        return json.loads(json_file_path)

    def generate(self) -> str:
        """
        Generates an HTML string that represents the parsed data.

        Returns:
            The generated HTML string.
        """

        html = f"<html>\n<!-- This content was generated by Wayback Tweets. Visit: https://claromes.github.io/waybacktweets -->\n"
        html += f"\n<head>\n<title>@{self.username}'s archived tweets</title>\n"
        html += "<style>\n"
        html += "body { font-family: monospace; background-color: whitesmoke; color: #1c1e21; margin: 0; padding: 20px; }\n"
        html += ".container { display: flex; flex-wrap: wrap; gap: 20px; }\n"
        html += ".tweet { flex: 0 1 calc(33.33% - 20px); background-color: #ffffff; border: 1px solid #e2e2e2; border-radius: 10px; padding: 15px; overflow-wrap: break-word; margin: auto; width: 600px; }\n"
        html += ".tweet strong { font-weight: bold; }\n"
        html += ".tweet a { color: #000000; text-decoration: none; }\n"
        html += ".content { color: #000000; }\n"
        html += ".source { font-size: 12px; text-align: center; }\n"
        html += ".iframe_text { font-size: 12px; text-align: end; }\n"
        html += ".tweet a:hover { text-decoration: underline; }\n"
        html += "h1, h3 { text-align: center; }\n"
        html += "iframe { width: 600px; height: 600px; }\n"
        html += "input {\n"
        html += "position: absolute;\n"
        html += "opacity: 0;\n"
        html += "z-index: -1;\n"
        html += "}\n"
        html += ".accordion {\n"
        html += "margin: 10px;\n"
        html += "border-radius: 5px;\n"
        html += "overflow: hidden;\n"
        html += "box-shadow: 0 4px 4px -2px rgba(0, 0, 0, 0.4);\n"
        html += "}\n"
        html += ".accordion-label {\n"
        html += "display: flex;\n"
        html += "justify-content: space-between;\n"
        html += "padding: 1em;\n"
        html += "font-weight: bold;\n"
        html += "cursor: pointer;\n"
        html += "background: #000000;\n"
        html += "color: #ffffff;\n"
        html += "}\n"
        html += ".accordion-content {\n"
        html += "max-height: 0;\n"
        html += "padding: 0 1em;\n"
        html += "background: white;\n"
        html += "transition: all 0.35s;\n"
        html += "}\n"
        html += "input:checked ~ .accordion-content {\n"
        html += "max-height: 100vh;\n"
        html += " padding: 1em;\n"
        html += "}\n"
        html += "</style>\n"
        html += "</head>\n<body>\n"
        html += f"<h1>@{self.username}'s archived tweets</h1>\n"
        html += '<div class="container">\n'

        for index, tweet in enumerate(self.json_file_path):
            html += '<div class="tweet">\n'

            if not tweet["available_tweet_text"]:
                iframe_src = {
                    "Archived Tweet": tweet["archived_tweet_url"],
                    "Parsed Archived Tweet": tweet["parsed_archived_tweet_url"],
                    "Original Tweet": tweet["original_tweet_url"],
                    "Parsed Tweet": tweet["parsed_tweet_url"],
                }

                html += f'<p class="source">{tweet["original_tweet_url"]}</p>\n'
                html += f'<p class="source">{tweet["archived_mimetype"]}</p>\n'
                html += "<br>\n"

                for key, value in iframe_src.items():
                    key_cleaned = key.replace(" ", "_")

                    html += f'<p class="iframe_text"><a href="{value}" target="_blank"><strong>{key}↗</strong></a>\n'
                    html += '<div class="accordion">\n'
                    html += (
                        f'<input type="checkbox" id="tab_{index}_{key_cleaned}" />\n'
                    )
                    html += f'<label class="accordion-label" for="tab_{index}_{key_cleaned}">Click to load the iframe from {key}</label>\n'
                    html += '<div class="accordion-content">\n'

                    html += f'<div id="loading_{index}_{key_cleaned}" class="loading">Loading...</div>\n'
                    html += f'<iframe id="iframe_{index}_{key_cleaned}" frameborder="0" scrolling="auto" loading="lazy" style="display: none;" onload="document.getElementById(\'loading_{index}_{key_cleaned}\').style.display=\'none\'; this.style.display=\'block\';"></iframe>\n'
                    html += "</div>\n"
                    html += "</div>\n"

                    html += """
                    <script>
                    document.getElementById('tab_{index}_{key_cleaned}').addEventListener('change', function() {{
                        if (this.checked) {{
                            document.getElementById('loading_{index}_{key_cleaned}').style.display = 'block';
                            document.getElementById('iframe_{index}_{key_cleaned}').src = '{url}';
                        }}
                    }});
                    </script>
                    """.format(
                        index=index, url=value, key_cleaned=key_cleaned
                    )

            if tweet["available_tweet_text"]:
                html += "<br>\n"
                html += f'<p><strong class="content">Available Tweet Content:</strong> {tweet["available_tweet_text"]}</p>\n'
                html += f'<p><strong class="content">Available Tweet Is Retweet:</strong> {tweet["available_tweet_is_RT"]}</p>\n'
                html += f'<p><strong class="content">Available Tweet Username:</strong> {tweet["available_tweet_info"]}</p>\n'

            html += "<br>\n"
            html += f'<p><strong>Archived URL Key:</strong> {tweet["archived_urlkey"]}</p>\n'
            html += f'<p><strong>Archived Timestamp:</strong> {timestamp_parser(tweet["archived_timestamp"])} ({tweet["archived_timestamp"]})</p>\n'
            html += f'<p><strong>Archived mimetype:</strong> {tweet["archived_mimetype"]}</p>\n'
            html += f'<p><strong>Archived Statuscode:</strong> {tweet["archived_statuscode"]}</p>\n'
            html += (
                f'<p><strong>Archived Digest:</strong> {tweet["archived_digest"]}</p>\n'
            )
            html += (
                f'<p><strong>Archived Length:</strong> {tweet["archived_length"]}</p>\n'
            )
            html += "</div>\n"

        html += "</div>\n"
        html += '<p class="source">generated by <a href="https://claromes.github.io/waybacktweets/" target="_blank">Wayback Tweets↗</a></p>\n'
        html += "</body>\n</html>"

        return html

    def save(self, html_content: str) -> None:
        """
        Saves the generated HTML string to a file.

        Args:
            html_content (str): The HTML string to be saved.
        """
        with open(self.html_file_path, "w", encoding="utf-8") as f:
            f.write(html_content)
