from __future__ import annotations

from textual.app import ComposeResult
from textual.binding import Binding
from textual.containers import Horizontal
from textual.widgets import DataTable, Static
from textual.widget import Widget

from django.db import models

from django_shreck.messages import GoBack
from django_shreck.services.model_introspection import ModelIntrospectionService


class CompareWidget(Widget):
    """Displays N Django model instances side by side, highlighting rows that differ."""

    BINDINGS = [
        Binding("escape", "go_back", "Back to list", show=True),
    ]

    DEFAULT_CSS = """
    CompareWidget {
        height: 100%;
        layout: vertical;
    }
    CompareWidget #compare-header {
        height: 1;
        content-align: center middle;
        background: $primary;
        color: $text;
        text-style: bold;
    }
    CompareWidget #compare-container {
        height: 1fr;
        layout: horizontal;
    }
    CompareWidget .compare-panel {
        width: 1fr;
        border: solid $secondary;
    }
    """

    def __init__(self, instances: list[models.Model], **kwargs) -> None:
        super().__init__(**kwargs)
        self._instances = instances

    def compose(self) -> ComposeResult:
        if not self._instances:
            yield Static("No instances to compare.", id="compare-header")
            return

        meta = self._instances[0]._meta
        pks = ", ".join(f"pk={inst.pk}" for inst in self._instances)
        title = f"Comparing: {meta.app_label}.{meta.model_name} — {pks}"
        yield Static(title, id="compare-header")

        with Horizontal(id="compare-container"):
            for i, instance in enumerate(self._instances):
                yield self._build_table(instance, i)

    def _build_table(self, instance: models.Model, index: int) -> DataTable:
        """Build a DataTable for one instance, highlighting differing fields."""
        table = DataTable(id=f"compare-{index}", classes="compare-panel")
        table.add_columns("Field", "Value")

        data = ModelIntrospectionService.get_instance_display_data(instance)

        # Collect values for all instances per field for diff detection
        all_data = [
            ModelIntrospectionService.get_instance_display_data(inst)
            for inst in self._instances
        ]

        # Build a map: field_name -> set of values across all instances
        field_values: dict[str, set] = {}
        for inst_data in all_data:
            for field_name, _field_type, value in inst_data:
                field_values.setdefault(field_name, set()).add(value)

        for field_name, field_type, value in data:
            differs = len(field_values.get(field_name, set())) > 1
            if differs:
                label = f"[bold yellow]{field_name}[/bold yellow]"
                display_value = f"[yellow]{value}[/yellow]"
            else:
                label = field_name
                display_value = value
            table.add_row(label, display_value)

        return table

    def action_go_back(self) -> None:
        """Navigate back to the queryset listing."""
        self.post_message(GoBack())

