"""
Built-in formatter plugins for MarkiTect.

These formatters provide various output formats for MarkiTect data.
"""

import json
import yaml
from typing import Any

from ..base import FormatterPlugin, PluginMetadata, PluginType
from ..decorators import register_plugin


@register_plugin("json_formatter")
class JsonFormatter(FormatterPlugin):
    """JSON output formatter."""

    @property
    def metadata(self) -> PluginMetadata:
        return PluginMetadata(
            name="json_formatter",
            version="1.0.0",
            description="Format output as JSON",
            author="MarkiTect Team",
            plugin_type=PluginType.FORMATTER
        )

    def format(self, data: Any, **kwargs) -> str:
        """Format data as JSON."""
        indent = kwargs.get('indent', 2)
        ensure_ascii = kwargs.get('ensure_ascii', False)

        return json.dumps(data, indent=indent, ensure_ascii=ensure_ascii)

    def get_file_extension(self) -> str:
        """Get JSON file extension."""
        return '.json'


@register_plugin("yaml_formatter")
class YamlFormatter(FormatterPlugin):
    """YAML output formatter."""

    @property
    def metadata(self) -> PluginMetadata:
        return PluginMetadata(
            name="yaml_formatter",
            version="1.0.0",
            description="Format output as YAML",
            author="MarkiTect Team",
            plugin_type=PluginType.FORMATTER
        )

    def format(self, data: Any, **kwargs) -> str:
        """Format data as YAML."""
        default_flow_style = kwargs.get('default_flow_style', False)
        indent = kwargs.get('indent', 2)

        return yaml.dump(data, default_flow_style=default_flow_style, indent=indent)

    def get_file_extension(self) -> str:
        """Get YAML file extension."""
        return '.yaml'


@register_plugin("table_formatter")
class TableFormatter(FormatterPlugin):
    """Table output formatter for structured data."""

    @property
    def metadata(self) -> PluginMetadata:
        return PluginMetadata(
            name="table_formatter",
            version="1.0.0",
            description="Format output as ASCII table",
            author="MarkiTect Team",
            plugin_type=PluginType.FORMATTER
        )

    def format(self, data: Any, **kwargs) -> str:
        """Format data as ASCII table."""
        if not isinstance(data, (list, tuple)):
            return str(data)

        if not data:
            return "No data"

        # Handle list of dictionaries (most common case)
        if isinstance(data[0], dict):
            return self._format_dict_table(data, **kwargs)

        # Handle simple list
        return self._format_simple_table(data, **kwargs)

    def _format_dict_table(self, data: list, **kwargs) -> str:
        """Format list of dictionaries as table."""
        if not data:
            return "No data"

        # Get all unique keys
        all_keys = set()
        for item in data:
            if isinstance(item, dict):
                all_keys.update(item.keys())

        headers = sorted(all_keys)

        # Calculate column widths
        col_widths = {}
        for header in headers:
            col_widths[header] = len(str(header))
            for item in data:
                if isinstance(item, dict) and header in item:
                    col_widths[header] = max(col_widths[header], len(str(item[header])))

        # Build table
        lines = []

        # Header
        header_line = "| " + " | ".join(h.ljust(col_widths[h]) for h in headers) + " |"
        lines.append(header_line)

        # Separator
        sep_line = "|-" + "-|-".join("-" * col_widths[h] for h in headers) + "-|"
        lines.append(sep_line)

        # Data rows
        for item in data:
            if isinstance(item, dict):
                row_line = "| " + " | ".join(
                    str(item.get(h, "")).ljust(col_widths[h]) for h in headers
                ) + " |"
                lines.append(row_line)

        return "\n".join(lines)

    def _format_simple_table(self, data: list, **kwargs) -> str:
        """Format simple list as single-column table."""
        max_width = max(len(str(item)) for item in data)
        max_width = max(max_width, len("Value"))

        lines = []
        lines.append(f"| {'Value'.ljust(max_width)} |")
        lines.append(f"|-{'-' * max_width}-|")

        for item in data:
            lines.append(f"| {str(item).ljust(max_width)} |")

        return "\n".join(lines)

    def get_file_extension(self) -> str:
        """Get table file extension."""
        return '.txt'