"""
Data table management for the hosts TUI application.

This module handles table population, sorting, filtering, and
row selection functionality.
"""

from rich.text import Text
from textual.widgets import DataTable
from typing import List

from ..core.models import HostEntry


class TableHandler:
    """Handles all data table operations for the hosts manager."""

    def __init__(self, app):
        """Initialize the table handler with reference to the main app."""
        self.app = app

    def get_visible_entries(self) -> List[HostEntry]:
        """Get the list of entries that are visible in the table (after filtering)."""
        show_defaults = self.app.config.should_show_default_entries()
        all_entries = []

        # First apply default entry filtering (legacy config setting)
        for entry in self.app.hosts_file.entries:
            canonical_hostname = entry.hostnames[0] if entry.hostnames else ""
            # Skip default entries if configured to hide them
            if not show_defaults and self.app.config.is_default_entry(
                entry.ip_address, canonical_hostname
            ):
                continue
            all_entries.append(entry)

        # Apply advanced filtering if enabled
        if hasattr(self.app, 'entry_filter') and hasattr(self.app, 'current_filter_options'):
            filtered_entries = self.app.entry_filter.apply_filters(all_entries, self.app.current_filter_options)
        else:
            # Fallback to legacy search filtering for backward compatibility
            filtered_entries = self._apply_legacy_search_filter(all_entries)

        return filtered_entries

    def _apply_legacy_search_filter(self, entries: List[HostEntry]) -> List[HostEntry]:
        """Apply legacy search filter for backward compatibility."""
        if not hasattr(self.app, 'search_term') or not self.app.search_term:
            return entries

        search_term_lower = self.app.search_term.lower()
        filtered_entries = []

        for entry in entries:
            matches_search = False

            # Search in IP address
            if search_term_lower in entry.ip_address.lower():
                matches_search = True

            # Search in hostnames
            if not matches_search:
                for hostname in entry.hostnames:
                    if search_term_lower in hostname.lower():
                        matches_search = True
                        break

            # Search in comment
            if not matches_search and entry.comment:
                if search_term_lower in entry.comment.lower():
                    matches_search = True

            if matches_search:
                filtered_entries.append(entry)

        return filtered_entries

    def get_first_visible_entry_index(self) -> int:
        """Get the index of the first visible entry in the hosts file."""
        show_defaults = self.app.config.should_show_default_entries()

        for i, entry in enumerate(self.app.hosts_file.entries):
            canonical_hostname = entry.hostnames[0] if entry.hostnames else ""
            # Skip default entries if configured to hide them
            if not show_defaults and self.app.config.is_default_entry(
                entry.ip_address, canonical_hostname
            ):
                continue
            return i

        # If no visible entries found, return 0
        return 0

    def display_index_to_actual_index(self, display_index: int) -> int:
        """Convert a display table index to the actual hosts file entry index."""
        visible_entries = self.get_visible_entries()
        if display_index >= len(visible_entries):
            return 0

        target_entry = visible_entries[display_index]

        # Find this entry in the full hosts file
        for i, entry in enumerate(self.app.hosts_file.entries):
            if entry is target_entry:
                return i

        return 0

    def actual_index_to_display_index(self, actual_index: int) -> int:
        """Convert an actual hosts file entry index to a display table index."""
        if actual_index >= len(self.app.hosts_file.entries):
            return 0

        target_entry = self.app.hosts_file.entries[actual_index]
        visible_entries = self.get_visible_entries()

        # Find this entry in the visible entries
        for i, entry in enumerate(visible_entries):
            if entry is target_entry:
                return i

        return 0

    def populate_entries_table(self) -> None:
        """Populate the left pane with hosts entries using DataTable."""
        table = self.app.query_one("#entries-table", DataTable)
        table.clear(columns=True)  # Clear both rows and columns

        # Configure DataTable properties
        table.zebra_stripes = True
        table.cursor_type = "row"
        table.show_header = True

        # Create column labels with sort indicators
        active_label = "Active"
        ip_label = "IP Address"
        hostname_label = "Canonical Hostname"
        dns_label = "DNS"

        # Add sort indicators
        if self.app.sort_column == "ip":
            arrow = "↑" if self.app.sort_ascending else "↓"
            ip_label = f"{arrow} IP Address"
        elif self.app.sort_column == "hostname":
            arrow = "↑" if self.app.sort_ascending else "↓"
            hostname_label = f"{arrow} Canonical Hostname"

        # Add columns with proper labels (Active, IP, Hostname, DNS)
        table.add_columns(active_label, ip_label, hostname_label, dns_label)

        # Get visible entries (after filtering)
        visible_entries = self.get_visible_entries()

        # Add rows
        for entry in visible_entries:
            # Get the canonical hostname (first hostname)
            canonical_hostname = entry.hostnames[0] if entry.hostnames else ""

            # Check if this is a default system entry
            is_default = entry.is_default_entry()

            # Get DNS status indicator
            dns_text = self._get_dns_status_indicator(entry)

            # Add row with styling based on active status and default entry status
            if is_default:
                # Default entries are always shown in dim grey regardless of active status
                active_text = Text("✓" if entry.is_active else "", style="dim white")
                ip_text = Text(entry.ip_address, style="dim white")
                hostname_text = Text(canonical_hostname, style="dim white")
                table.add_row(active_text, ip_text, hostname_text, dns_text)
            elif entry.is_active:
                # Active entries in green with checkmark
                active_text = Text("✓", style="bold green")
                ip_text = Text(entry.ip_address, style="bold green")
                hostname_text = Text(canonical_hostname, style="bold green")
                table.add_row(active_text, ip_text, hostname_text, dns_text)
            else:
                # Inactive entries in dim yellow with italic (no checkmark)
                active_text = Text("", style="dim yellow italic")
                ip_text = Text(entry.ip_address, style="dim yellow italic")
                hostname_text = Text(canonical_hostname, style="dim yellow italic")
                table.add_row(active_text, ip_text, hostname_text, dns_text)

    def restore_cursor_position(self, previous_entry) -> None:
        """Restore cursor position after reload, maintaining selection if possible."""
        if not self.app.hosts_file.entries:
            self.app.selected_entry_index = 0
            return

        if previous_entry is None:
            # No previous selection, start at first visible entry
            self.app.selected_entry_index = self.get_first_visible_entry_index()
        else:
            # Try to find the same entry in the reloaded file
            for i, entry in enumerate(self.app.hosts_file.entries):
                if (
                    entry.ip_address == previous_entry.ip_address
                    and entry.hostnames == previous_entry.hostnames
                    and entry.comment == previous_entry.comment
                ):
                    self.app.selected_entry_index = i
                    break
            else:
                # Entry not found, default to first visible entry
                self.app.selected_entry_index = self.get_first_visible_entry_index()

        # Update the DataTable cursor position using display index
        table = self.app.query_one("#entries-table", DataTable)
        display_index = self.actual_index_to_display_index(
            self.app.selected_entry_index
        )
        if table.row_count > 0 and display_index < table.row_count:
            # Move cursor to the selected row
            table.move_cursor(row=display_index)
            table.focus()
            # Update the details pane to match the selection
            self.app.details_handler.update_entry_details()

    def sort_entries_by_ip(self) -> None:
        """Sort entries by IP address."""
        if self.app.sort_column == "ip":
            # Toggle sort direction if already sorting by IP
            self.app.sort_ascending = not self.app.sort_ascending
        else:
            # Set new sort column and default to ascending
            self.app.sort_column = "ip"
            self.app.sort_ascending = True

        # Remember the currently selected entry
        current_entry = None
        if self.app.hosts_file.entries and self.app.selected_entry_index < len(
            self.app.hosts_file.entries
        ):
            current_entry = self.app.hosts_file.entries[self.app.selected_entry_index]

        # Sort the entries
        self.app.hosts_file.entries.sort(
            key=lambda entry: entry.ip_address, reverse=not self.app.sort_ascending
        )

        # Refresh the table and restore cursor position
        self.populate_entries_table()
        self.restore_cursor_position(current_entry)

    def _get_dns_status_indicator(self, entry) -> Text:
        """Get DNS name and status indicator for an entry."""
        # If entry has no DNS name configured, show empty
        if not entry.has_dns_name():
            return Text("", style="dim white")

        # Start with the DNS name
        dns_display = entry.dns_name
        
        # Add status indicator based on resolution status
        dns_status = entry.dns_resolution_status or "not_resolved"
        
        if dns_status == "not_resolved":
            status_icon = "⏳"
            style = "dim yellow"
        elif dns_status == "resolving":
            status_icon = "🔄"
            style = "yellow"
        elif dns_status == "resolved":
            status_icon = "✅"
            style = "green"
        elif dns_status == "match":
            status_icon = "✅"
            style = "bold green"
        elif dns_status == "mismatch":
            status_icon = "⚠️"
            style = "red"
        elif dns_status == "failed":
            status_icon = "❌"
            style = "red"
        else:
            status_icon = ""
            style = "dim white"
        
        return Text(f"{status_icon} {dns_display}", style=style)

    def sort_entries_by_hostname(self) -> None:
        """Sort entries by canonical hostname."""
        if self.app.sort_column == "hostname":
            # Toggle sort direction if already sorting by hostname
            self.app.sort_ascending = not self.app.sort_ascending
        else:
            # Set new sort column and default to ascending
            self.app.sort_column = "hostname"
            self.app.sort_ascending = True

        # Remember the currently selected entry
        current_entry = None
        if self.app.hosts_file.entries and self.app.selected_entry_index < len(
            self.app.hosts_file.entries
        ):
            current_entry = self.app.hosts_file.entries[self.app.selected_entry_index]

        # Sort the entries
        self.app.hosts_file.entries.sort(
            key=lambda entry: entry.hostnames[0].lower() if entry.hostnames else "",
            reverse=not self.app.sort_ascending,
        )

        # Refresh the table and restore cursor position
        self.populate_entries_table()
        self.restore_cursor_position(current_entry)
