"""
Preset pack encoder with ASCII art compression.

Compresses plugin code and encodes it as ASCII art for fun and version control.
"""

import base64
import zlib
import textwrap
from typing import Tuple


class PresetPackEncoder:
    """Encodes and decodes preset packs with ASCII art compression."""

    # ASCII art frame characters
    FRAME_TOP_LEFT = "┌"
    FRAME_TOP_RIGHT = "┐"
    FRAME_BOTTOM_LEFT = "└"
    FRAME_BOTTOM_RIGHT = "┘"
    FRAME_HORIZONTAL = "─"
    FRAME_VERTICAL = "│"

    # Data block characters (for visual representation)
    DATA_CHARS = " ░▒▓█"

    @classmethod
    def encode_plugin_code(cls, code: str, name: str = "plugin") -> str:
        """Encode plugin code as ASCII art.

        Args:
            code: Python source code to encode
            name: Plugin name for metadata

        Returns:
            ASCII art encoded plugin code
        """
        # Compress the code
        compressed = zlib.compress(code.encode("utf-8"))

        # Encode as base64
        b64 = base64.b64encode(compressed).decode("ascii")

        # Wrap in ASCII art frame
        return cls._wrap_in_ascii_art(b64, name)

    @classmethod
    def decode_plugin_code(cls, ascii_art: str) -> str:
        """Decode ASCII art to plugin code.

        Args:
            ascii_art: ASCII art encoded plugin code

        Returns:
            Decoded Python source code
        """
        # Extract base64 from ASCII art
        b64 = cls._extract_from_ascii_art(ascii_art)

        # Decode base64
        compressed = base64.b64decode(b64)

        # Decompress
        code = zlib.decompress(compressed).decode("utf-8")

        return code

    @classmethod
    def _wrap_in_ascii_art(cls, data: str, name: str) -> str:
        """Wrap data in ASCII art frame."""
        # Calculate frame width
        max_line_length = 60
        lines = textwrap.wrap(data, max_line_length)

        # Find longest line for frame width
        longest_line = max(len(line) for line in lines) if lines else 0
        frame_width = longest_line + 4  # 2 padding + 2 borders

        # Build ASCII art
        result = []

        # Top border
        result.append(
            cls.FRAME_TOP_LEFT
            + cls.FRAME_HORIZONTAL * (frame_width - 2)
            + cls.FRAME_TOP_RIGHT
        )

        # Plugin name header
        name_line = f" {name} "
        name_padding = frame_width - 2 - len(name_line)
        left_pad = name_padding // 2
        right_pad = name_padding - left_pad
        result.append(
            cls.FRAME_VERTICAL
            + " " * left_pad
            + name_line
            + " " * right_pad
            + cls.FRAME_VERTICAL
        )

        # Separator line
        result.append(
            cls.FRAME_VERTICAL
            + cls.FRAME_HORIZONTAL * (frame_width - 2)
            + cls.FRAME_VERTICAL
        )

        # Data lines
        for line in lines:
            padding = frame_width - 2 - len(line)
            result.append(
                cls.FRAME_VERTICAL + line + " " * padding + cls.FRAME_VERTICAL
            )

        # Bottom border
        result.append(
            cls.FRAME_BOTTOM_LEFT
            + cls.FRAME_HORIZONTAL * (frame_width - 2)
            + cls.FRAME_BOTTOM_RIGHT
        )

        return "\n".join(result)

    @classmethod
    def _extract_from_ascii_art(cls, ascii_art: str) -> str:
        """Extract base64 data from ASCII art frame."""
        lines = ascii_art.strip().split("\n")

        # Skip top and bottom borders, header, and separator
        data_lines = lines[3:-1]

        # Extract data from between frame characters
        extracted = []
        for line in data_lines:
            if len(line) > 2:
                # Remove frame characters and extract content
                content = line[1:-1].rstrip()
                extracted.append(content)

        return "".join(extracted)

    @classmethod
    def encode_toml(cls, toml_data: str, name: str = "pack") -> str:
        """Encode TOML data as ASCII art.

        Args:
            toml_data: TOML configuration data
            name: Pack name

        Returns:
            ASCII art encoded TOML
        """
        # Compress
        compressed = zlib.compress(toml_data.encode("utf-8"))

        # Encode as base64
        b64 = base64.b64encode(compressed).decode("ascii")

        # Create visual representation using data characters
        visual_data = cls._data_to_visual(b64)

        return cls._wrap_in_ascii_art(visual_data, name)

    @classmethod
    def decode_toml(cls, ascii_art: str) -> str:
        """Decode ASCII art to TOML data.

        Args:
            ascii_art: ASCII art encoded TOML

        Returns:
            Decoded TOML data
        """
        # Extract base64 from ASCII art
        b64 = cls._extract_from_ascii_art(ascii_art)

        # Decode base64
        compressed = base64.b64decode(b64)

        # Decompress
        toml_data = zlib.decompress(compressed).decode("utf-8")

        return toml_data

    @classmethod
    def _data_to_visual(cls, data: str) -> str:
        """Convert base64 data to visual representation.

        This creates a fun visual pattern based on the data.
        """
        # Simple mapping: each character to a data block character
        # This is purely for visual appeal
        visual = ""
        for i, char in enumerate(data):
            # Use character code to select visual block
            idx = ord(char) % len(cls.DATA_CHARS)
            visual += cls.DATA_CHARS[idx]

            # Add line breaks for visual appeal
            if (i + 1) % 60 == 0:
                visual += "\n"

        return visual

    @classmethod
    def get_visual_representation(cls, data: str) -> str:
        """Get a visual representation of data for display."""
        compressed = zlib.compress(data.encode("utf-8"))
        b64 = base64.b64encode(compressed).decode("ascii")
        return cls._data_to_visual(b64)
