import django_tables2 as tables
from django_tables2.utils import A

from generic.tables import SeriesImageColumn, SelectionTable

from .models import (
    Case,
    CaseCollection,
    Condition,
    PathologicalProcess,
    Presentation,
    QuestionSchema,
    Series,
    Structure,
    Finding,
    Subspecialty,
    Resource,
    Procedure,
)

from django.utils.html import format_html

from django.utils.safestring import mark_safe
from django.template.defaultfilters import filesizeformat

from easy_thumbnails.files import get_thumbnailer

from easy_thumbnails.exceptions import InvalidImageFormatError

from django.db.models import Prefetch


class CaseTable(SelectionTable):
    def __init__(self, data=None, *args, **kwargs):
        # Optimize prefetching for casecollection_set
        #case_collections_prefetch = Prefetch(
        #    "casecollection_set",
        #    queryset=CaseCollection.objects.select_related("author"),  # Adjust fields as needed
        #)

        super().__init__(
            data.prefetch_related(
                "author",  # Many-to-many or reverse relationship
                "series",  # Many-to-many relationship
                "series__examination",  # ForeignKey in the related model
                "series__plane",  # ForeignKey in the related model
                "series__images",  # Reverse relationship
                "previous_case",  # Prefetch the previous case relationship
                "next_case",  # Prefetch the next case relationship
                "casecollection_set",  # Prefetch the case collection set
                #case_collections_prefetch,  # Optimized prefetch for collections
            ),
            *args,
            **kwargs,
        )

    def render_title(self, value, record):
        return value

    def render_description(self, value):
        max_length = 50  # Set the maximum length for truncation
        if len(value) > max_length:
            truncated_value = f"{value[:max_length]}..."  # Truncate and add ellipsis
        else:
            truncated_value = value
        # Add a tooltip with the full text
        return format_html(
            '<span title="{}">{}</span>',
            value,  # Full text for the tooltip
            truncated_value,  # Truncated text for display
        )

    def render_series(self, value):
        max_length = 50  # Set the maximum length for truncation
        series_list = [str(series) for series in value.all()]
        full_text = ", ".join(series_list)  # Full text for the tooltip
        if len(full_text) > max_length:
            truncated_text = f"{full_text[:max_length]}..."  # Truncate and add ellipsis
        else:
            truncated_text = full_text
        # Add a tooltip with the full text
        return format_html(
            '<span title="{}">{}</span>',
            full_text,  # Full text for the tooltip
            truncated_text,  # Truncated text for display
        )

    def get_view_cell(record):
        if record.open_access:
            return mark_safe(
                '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-opencollective" viewBox="0 0 16 16">'
                '<path fill-opacity=".4" d="M12.995 8.195c0 .937-.312 1.912-.78 2.693l1.99 1.99c.976-1.327 1.6-2.966 1.6-4.683 0-1.795-.624-3.434-1.561-4.76l-2.068 2.028c.468.781.78 1.679.78 2.732h.04Z"/>'
                '<path d="M8 13.151a4.995 4.995 0 1 1 0-9.99c1.015 0 1.951.273 2.732.82l1.95-2.03a7.805 7.805 0 1 0 .04 12.449l-1.951-2.03a5.072 5.072 0 0 1-2.732.781z"/>'
                '</svg> View'
            )
        else:
            return 'View'

    def render_author(self, value):
        max_length = 15  # Set the maximum length for truncating individual author names
        authors = []
        for author in value.all():
            full_name = str(author)  # Convert the author object to a string (e.g., full name)
            if len(full_name) > max_length:
                truncated_name = f"{full_name[:max_length]}..."  # Truncate and add ellipsis
            else:
                truncated_name = full_name
            # Add a tooltip with the full name
            authors.append(
                format_html(
                    '<span title="{}">{}</span>',
                    full_name,  # Full name for the tooltip
                    truncated_name,  # Truncated name for display
                )
            )
        # Join all authors with commas
        return mark_safe(", ".join(authors))

    def render_associated_cases(self, record):
        links = []
        if record.previous_case:
            links.append(
                format_html(
                    '<a href="{}" title="View previous case">Previous Case</a>',
                    record.previous_case.get_absolute_url(),
                )
            )
        try:
            if record.next_case:
                links.append(
                    format_html(
                        '<a href="{}" title="View next case">Next Case</a>',
                        record.next_case.get_absolute_url(),
                    )
                )
        except Case.DoesNotExist:
            pass
        if links:
            return mark_safe(", ".join(links))
        return "No associated cases"

    def render_collections(self, record):
        collections = [
            collection
            for collection in record.casecollection_set.all()
            if (
            hasattr(self, 'request')
            and self.request.user in collection.author.all()
            ) or collection.open_access
        ]
        if collections:
            links = [
                format_html(
                    '<a href="{}" title="View collection">{}</a>',
                    collection.get_absolute_url(),
                    collection.name,
                )
                for collection in collections
            ]
            return mark_safe(", ".join(links))
        return "No collections"


    associated_cases = tables.Column(
        verbose_name="Associated Cases", accessor="pk", orderable=False
    )

    collections = tables.Column(
        verbose_name="Collections", accessor="pk", orderable=False
    )

    edit = tables.LinkColumn(
        "atlas:case_update", text="Edit", args=[A("pk")], orderable=False
    )
    view = tables.LinkColumn(
        "atlas:case_detail", text=get_view_cell, args=[A("pk")], accessor="pk", orderable=False
    )
    clone = tables.LinkColumn(
        "atlas:case_clone", text="Clone", args=[A("pk")], orderable=False
    )
    delete = tables.LinkColumn(
        "atlas:case_delete", text="Delete", args=[A("pk")], orderable=False
    )


    class Meta(SelectionTable.Meta):
        model = Case
        template_name = "django_tables2/bootstrap4.html"
        fields = (
            "title",
            "description",
            "created_date",
            "series",
            "author",
            "associated_cases",
            "collections",
        )
        sequence = ("view", )
        order_by = "-created_date"



class PopupLinkColumn(tables.Column):
    def render(self, value):
        return format_html("<span>test: {}<span>", value)
        obj = value.first()

        if obj is None:
            return mark_safe("<span>No image</span>")

        return obj.get_thumbnail()[0]


class SeriesTable(SelectionTable):
    edit = tables.LinkColumn(
        "atlas:series_update", text="Edit", args=[A("pk")], orderable=False
    )
    view = tables.LinkColumn(
        "atlas:series_detail", text="View", args=[A("pk")], accessor="pk", orderable=False
    )
    popup = tables.Column(empty_values=(), orderable=False)

    images = SeriesImageColumn("Images", orderable=False)

    delete = tables.LinkColumn(
        "atlas:series_delete", text="Delete", args=[A("pk")], orderable=False
    )

    case = tables.ManyToManyColumn(verbose_name="Cases")
    findings = tables.ManyToManyColumn(verbose_name="Findings")
    structures = tables.ManyToManyColumn(verbose_name="Structures")

    class Meta(SelectionTable.Meta):
        model = Series
        template_name = "django_tables2/bootstrap4.html"
        fields = (
            "modality",
            "description",
            "examination",
            "plane",
            "contrast",
            "author",
            "created_date",
            "modified_date",
        )
        sequence = ("view", "popup", "images", "case")
        order_by = "-created_date"


    def __init__(self, data=None, *args, **kwargs):
        super().__init__(
            data.prefetch_related(
                "modality", "case", "examination", "plane", "contrast", "author", "findings", "images"
            ),
            *args,
            **kwargs,
        )

    def render_popup(self, value, record):
        return format_html(
            """<a href="#" onclick="return window.create_popup_window('/atlas/series/{}', 'Series')" >Popup</a>""",
            record.pk,
        )


class ConditionTable(SelectionTable):
    name = tables.Column(
        linkify=("atlas:condition_detail", {"pk": tables.A("pk")}),
        verbose_name="Condition",
    )

    edit = tables.LinkColumn(
        "atlas:condition_update", text="Edit", args=[A("pk")], orderable=False
    )
    delete = tables.LinkColumn(
        "atlas:condition_delete", text="Delete", args=[A("pk")], orderable=False
    )

    # synonym = tables.ManyToManyColumn(verbose_name="Synonyms")
    synonym = tables.Column(empty_values=())
    parent = tables.ManyToManyColumn(verbose_name="Parents")

    class Meta(SelectionTable.Meta):
        model = Condition
        template_name = "django_tables2/bootstrap4.html"
        fields = ("subspecialty", "rcr_curriculum_map", "rcr_curriculum")
        sequence = ("name",)


    def __init__(self, data=None, *args, **kwargs):
        super().__init__(
            data.prefetch_related(
                "subspecialty", "rcr_curriculum_map", "parent"
            ),
            *args,
            **kwargs,
        )

    def render_synonym(self, value, record):
        return mark_safe(record.get_synonym_link())
        return f"{record.get_synonym_link()}"


class FindingTable(SelectionTable):
    name = tables.Column(
        linkify=("atlas:finding_detail", {"pk": tables.A("pk")}), verbose_name="Finding"
    )
    edit = tables.LinkColumn(
        "atlas:finding_update", text="Edit", args=[A("pk")], orderable=False
    )
    delete = tables.LinkColumn(
        "atlas:finding_delete", text="Delete", args=[A("pk")], orderable=False
    )

    # synonym = tables.ManyToManyColumn(verbose_name="Synonyms")
    synonym = tables.Column(empty_values=())
    parent = tables.ManyToManyColumn(verbose_name="Parents")

    class Meta(SelectionTable.Meta):
        model = Finding
        template_name = "django_tables2/bootstrap4.html"
        fields = ("name",)
        sequence = ("name",)


    def render_synonym(self, value, record):
        return mark_safe(record.get_synonym_link())


class StructureTable(SelectionTable):
    name = tables.Column(
        linkify=("atlas:structure_detail", {"pk": tables.A("pk")}),
        verbose_name="Structure",
    )
    edit = tables.LinkColumn(
        "atlas:structure_update", text="Edit", args=[A("pk")], orderable=False
    )
    delete = tables.LinkColumn(
        "atlas:structure_delete", text="Delete", args=[A("pk")], orderable=False
    )

    # synonym = tables.ManyToManyColumn(verbose_name="Synonyms")
    synonym = tables.Column(empty_values=())
    parent = tables.ManyToManyColumn(verbose_name="Parents")

    class Meta(SelectionTable.Meta):
        model = Structure
        template_name = "django_tables2/bootstrap4.html"
        fields = ("name",)
        sequence = ("name",)


    def render_synonym(self, value, record):
        return mark_safe(record.get_synonym_link())


class PresentationTable(SelectionTable):
    name = tables.Column(
        linkify=("atlas:presentation_detail", {"pk": tables.A("pk")}),
        verbose_name="Presentation",
    )

    # edit = tables.LinkColumn(
    #    "atlas:presentation_update", text="Edit", args=[A("pk")], orderable=False
    # )
    # delete = tables.LinkColumn(
    #    "atlas:presentation_delete", text="Delete", args=[A("pk")], orderable=False
    # )

    subspecialty = tables.ManyToManyColumn(verbose_name="Subspecialty")

    class Meta(SelectionTable.Meta):
        model = Presentation
        template_name = "django_tables2/bootstrap4.html"
        fields = ("name",)
        sequence = ("name",)
        



class PathologicalProcessTable(SelectionTable):
    name = tables.Column(
        linkify=("atlas:pathological_process_detail", {"pk": tables.A("pk")}),
        verbose_name="PathologicalProcess",
    )

    # edit = tables.LinkColumn(
    #    "atlas:pathological_process_update", text="Edit", args=[A("pk")], orderable=False
    # )
    # delete = tables.LinkColumn(
    #    "atlas:pathological_process_delete", text="Delete", args=[A("pk")], orderable=False
    # )

    class Meta(SelectionTable.Meta):
        model = PathologicalProcess
        template_name = "django_tables2/bootstrap4.html"
        fields = ("name",)
        sequence = ("name",)


class ProcedureTable(SelectionTable):
    name = tables.Column(
        linkify=("atlas:procedure_detail", {"pk": tables.A("pk")}),
        verbose_name="Procedure",
    )

    edit = tables.LinkColumn(
        "atlas:procedure_update", text="Edit", args=[A("pk")], orderable=False
    )
    delete = tables.LinkColumn(
        "atlas:procedure_delete", text="Delete", args=[A("pk")], orderable=False
    )

    class Meta(SelectionTable.Meta):
        model = Procedure
        template_name = "django_tables2/bootstrap4.html"
        fields = ("name",)
        sequence = ("name",)


class SubspecialtyTable(SelectionTable):
    name = tables.Column(
        linkify=("atlas:subspecialty_detail", {"pk": tables.A("pk")}),
        verbose_name="Subspecialty",
    )

    # edit = tables.LinkColumn(
    #    "atlas:subspecialty_update", text="Edit", args=[A("pk")], orderable=False
    # )
    # delete = tables.LinkColumn(
    #    "atlas:subspecialty_delete", text="Delete", args=[A("pk")], orderable=False
    # )

    class Meta(SelectionTable.Meta):
        model = Subspecialty
        template_name = "django_tables2/bootstrap4.html"
        fields = ()
        sequence = ("name",)


    def render_synonym(self, value, record):
        return mark_safe(record.get_synonym_link())
        return f"{record.get_synonym_link()}"


class ResourceTable(SelectionTable):
    name = tables.Column(linkify=("atlas:resource_detail", {"pk": tables.A("pk")}), verbose_name="Resource")

    edit = tables.LinkColumn("atlas:resource_update", text="Edit", args=[A("pk")], orderable=False)
    delete = tables.LinkColumn("atlas:resource_delete", text="Delete", args=[A("pk")], orderable=False)

    class Meta(SelectionTable.Meta):
        model = Resource
        template_name = "django_tables2/bootstrap4.html"
        fields = ("name", "description")

class CaseCollectionTable(SelectionTable):
    edit = tables.LinkColumn(
        "atlas:exam_update", text="Edit", args=[A("pk")], orderable=False
    )
    view = tables.LinkColumn(
        "atlas:collection_detail", text="View", args=[A("pk")], accessor="pk", orderable=False
    )

    created = tables.DateTimeColumn(verbose_name="Created", accessor="created", orderable=True)
    updated = tables.DateTimeColumn(verbose_name="Updated", accessor="updated", orderable=True)
    #clone = tables.LinkColumn(
    #    "atlas:case_clone", text="Clone", args=[A("pk")], orderable=False
    #)
    delete = tables.LinkColumn(
        "atlas:exam_deleted", text="Delete", args=[A("pk")], orderable=False
    )

    #differential = tables.ManyToManyColumn(verbose_name="Differential")


    class Meta(SelectionTable.Meta):
        model = CaseCollection
        template_name = "django_tables2/bootstrap4.html"
        fields = (
            "name",
            "created",
            "updated",
            "collection_type",
            "publish_results",
            "active",
            "author",
        )
        sequence = ("view", )#, "series")


    def __init__(self, data=None, *args, **kwargs):
        super().__init__(
            data.prefetch_related(
                "author", #"conditionI"", "condition__synonym"
            ),
            *args,
            **kwargs,
        )

    def render_created(self, value):
        if not value:
            return ""
        # compact date for display, full datetime in tooltip
        return format_html(
            '<span class="small text-muted" title="{}">{}</span>',
            value.strftime("%Y-%m-%d %H:%M"),
            value.strftime("%Y-%m-%d"),
        )

    def render_updated(self, value):
        if not value:
            return ""
        return format_html(
            '<span class="small text-muted" title="{}">{}</span>',
            value.strftime("%Y-%m-%d %H:%M"),
            value.strftime("%Y-%m-%d"),
        )

class QuestionSchemaTable(SelectionTable):
    name = tables.Column(
        linkify=("atlas:question_schema_detail", {"pk": tables.A("pk")}),
        verbose_name="QuestionSchema",
    )

    edit = tables.LinkColumn(
        "atlas:question_schema_update", text="Edit", args=[A("pk")], orderable=False
    )
    delete = tables.LinkColumn(
        "atlas:question_schema_delete", text="Delete", args=[A("pk")], orderable=False
    )

    class Meta(SelectionTable.Meta):
        model = QuestionSchema
        template_name = "django_tables2/bootstrap4.html"
        fields = ("name", "description", "schema")


    def render_schema(self, value, record):
        return format_html("<details><summary>Schema</summary>{}</details>", value)