"""
Various field components for read-only data display and formatting.
"""
from datetime import date, datetime, time
import logging
from .templatetags.markdown_extras import convert_markdown
from django.utils import timezone

from .base import Component

logger = logging.getLogger(__name__)


class Field(Component):
    """Base class for read-only data display fields."""
    pass


class TextField(Field):
    """A standard text display field."""
    def render_html(self, **kwargs) -> str:
        url = self.get_url(**kwargs)
        value = self.get_value(**kwargs)
        if url is None:
            return f"""
                <div id="{self.uid}" class="{self.classes}">{{% verbatim %}}{value}{{% endverbatim %}}</div>"""
        else:
            return f"""
                <a id="{self.uid}" class="{self.classes}" href="{url}">
                    {{% verbatim %}}{value}{{% endverbatim %}}
                </a>
            """


class TitleField(Field):
    """A large, bold text field for titles."""
    def render_html(self, **kwargs) -> str:
        value = self.get_value(**kwargs)
        return f"""
            <div id="{self.uid}" class="text-xl font-semibold text-primary {self.classes}">{{% verbatim %}}{value}{{% endverbatim %}}</div>"""


class SubtitleField(Field):
    """A muted text field for subtitles."""
    def render_html(self, **kwargs) -> str:
        value = self.get_value(**kwargs)
        return f"""
            <div id="{self.uid}" class="text-md text-gray-500">{{% verbatim %}}{value}{{% endverbatim %}}</div>"""


class DateTimeField(Field):
    """Formats and displays a datetime object using timezone localization."""
    def render_html(self, **kwargs) -> str:
        value = self.get_value(**kwargs)
        if value is None:
            return ""
        if isinstance(value, datetime):
            value = timezone.localtime(value)
            value_str = value.strftime("%d %B, %Y, %I:%M %p")
        else:
            value_str = str(value)
        return f"{{% verbatim %}}{value_str}{{% endverbatim %}}"


class DateField(Field):
    """Formats and displays a date object."""
    def render_html(self, **kwargs) -> str:
        value = self.get_value(**kwargs)
        if value is None:
            return ""
        if isinstance(value, date):
            value_str = value.strftime("%d %B, %Y")
        else:
            value_str = str(value)
        return f"{{% verbatim %}}{value_str}{{% endverbatim %}}"


class TimeField(Field):
    """Formats and displays a time object."""
    def render_html(self, **kwargs) -> str:
        value = self.get_value(**kwargs)
        if value is None:
            return ""
        if isinstance(value, time):
            value_str = value.strftime("%I:%M %p")
        else:
            value_str = str(value)
        return f"{{% verbatim %}}{value_str}{{% endverbatim %}}"


class CheckboxField(Field):
    """Displays a boolean value as a check or cross icon."""
    def render_html(self, **kwargs) -> str:
        value = self.get_value(**kwargs)
        if value:
            return f'<span id="{self.uid}">{{% heroicon_mini "check-circle" class="text-success" %}}</span>'
        return f'<span id="{self.uid}">{{% heroicon_mini "x-circle" class="text-error" %}}</span>'


class ManyToManyField(Field):
    """Displays a list of related objects, optionally as links."""
    def __init__(self, display_attr: str = "__str__", **kwargs):
        super().__init__(**kwargs)
        self.display_attr = display_attr

    def render_html(self, **kwargs) -> str:
        values = self.get_value(**kwargs)
        if not values:
            return ""

        if not isinstance(values, (list, tuple)):
            values = [values]

        items_html = []
        for item in values:
            display_val = (
                str(item)
                if self.display_attr == "__str__"
                else str(getattr(item, self.display_attr, item))
            )

            item_url = None
            if self.url is not None:
                if isinstance(self.url, str):
                    item_url = self.url
                elif callable(self.url):
                    item_url = self.url(item)

            if item_url:
                items_html.append(
                    f'<a href="{item_url}" class="link link-primary">{{% verbatim %}}{display_val}{{% endverbatim %}}</a>'
                )
            else:
                items_html.append(
                    f"<span>{{% verbatim %}}{display_val}{{% endverbatim %}}</span>"
                )

        content = ", ".join(items_html)
        return f'<div id="{self.uid}" class="{self.classes}">{content}</div>'


class MarkdownField(Field):
    """Renders raw markdown content into safe HTML prose."""
    def render_html(self, **kwargs) -> str:
        value = self.get_value(**kwargs)
        if not value:
            return ""

        html_content = convert_markdown(value)
        return f'<div id="{self.uid}" class="prose prose-sm max-w-none">{html_content}</div>'


class ListField(Field):
    """Iterates over a list of objects and renders child components for each."""
    def render_html(self, **kwargs) -> str:
        value = self.get_value(**kwargs)
        list_html = ""
        for row in value:
            list_html += "<div>"
            for component in self.children:
                list_html += component.build().render(**{**kwargs, "object": row})
            list_html += "</div>"

        return list_html


class AccordianField(Field):
    """A collapsible accordion panel."""
    def __init__(self, title: str | None = None, **kwargs):
        super().__init__(**kwargs)
        self.title = title

    def render_html(self, **kwargs) -> str:
        return f'''
        <div id="{self.uid}" class="{self.classes}">
            <div class="collapse collapse-arrow bg-base-200">
                <input type="checkbox" />
                <div class="collapse-title font-semibold">
                    {self.title}
                </div>
                <div class="collapse-content">
                    {"".join([child.build().render(**kwargs) for child in self.children])}
                </div>
            </div>
        </div>
        '''
