from __future__ import annotations

import tkinter as tk
from tkinter import ttk
from typing import Any, Dict, Iterable, Sequence

from gui.theme import COLORS


class Card(ttk.Frame):
    def __init__(self, parent, title: str, value: str = "N/A", compact: bool = False):
        super().__init__(parent, style="Panel.TFrame", padding=10 if compact else 14)
        self.columnconfigure(0, weight=1)
        ttk.Label(self, text=title.upper(), style="PanelMuted.TLabel", font=("Segoe UI Semibold", 8)).grid(sticky="w")
        self.value = ttk.Label(self, text=value, style="CardValue.TLabel")
        self.value.grid(sticky="w", pady=(6, 0))

    def set(self, value: Any, color: str | None = None) -> None:
        self.value.configure(text="N/A" if value is None else str(value), foreground=color or COLORS["text"])


class DataTable(ttk.Frame):
    def __init__(self, parent, columns: Sequence[tuple[str, str, int]], height: int = 14):
        super().__init__(parent, style="Panel.TFrame")
        self.columns = [item[0] for item in columns]
        self.tree = ttk.Treeview(self, columns=self.columns, show="headings", height=height)
        vertical = ttk.Scrollbar(self, orient="vertical", command=self.tree.yview)
        horizontal = ttk.Scrollbar(self, orient="horizontal", command=self.tree.xview)
        self.tree.configure(yscrollcommand=vertical.set, xscrollcommand=horizontal.set)
        self.tree.grid(row=0, column=0, sticky="nsew")
        vertical.grid(row=0, column=1, sticky="ns")
        horizontal.grid(row=1, column=0, sticky="ew")
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        self._sort_reverse: Dict[str, bool] = {}
        for key, label, width in columns:
            self.tree.heading(key, text=label, command=lambda name=key: self.sort(name))
            self.tree.column(key, width=width, minwidth=55, stretch=True)
        for severity, color in (("info", COLORS["good"]), ("low", COLORS["good"]),
                                ("medium", COLORS["warn"]), ("high", COLORS["high"]),
                                ("critical", COLORS["critical"])):
            self.tree.tag_configure(severity, foreground=color)

    def set_rows(self, rows: Iterable[Dict[str, Any]]) -> None:
        self.tree.delete(*self.tree.get_children())
        for row in rows:
            severity = str(row.get("severity", "")).lower()
            self.tree.insert("", "end", values=[row.get(key, "") for key in self.columns], tags=(severity,))

    def sort(self, column: str) -> None:
        reverse = self._sort_reverse.get(column, False)
        children = list(self.tree.get_children())
        children.sort(key=lambda item: str(self.tree.set(item, column)).lower(), reverse=reverse)
        for index, item in enumerate(children):
            self.tree.move(item, "", index)
        self._sort_reverse[column] = not reverse


class Page(ttk.Frame):
    def __init__(self, parent, title: str, subtitle: str = ""):
        super().__init__(parent, padding=(22, 18))
        self.columnconfigure(0, weight=1)
        ttk.Label(self, text=title, style="Title.TLabel").grid(row=0, column=0, sticky="w")
        if subtitle:
            ttk.Label(self, text=subtitle, style="Muted.TLabel").grid(row=1, column=0, sticky="w", pady=(2, 14))

    def refresh(self, snapshot: Dict[str, Any]) -> None:
        pass


class ReadOnlyDetailsDialog(tk.Toplevel):
    """Resizable, scrollable analyst-details window."""

    def __init__(self, parent, title: str, content: str):
        super().__init__(parent)
        self.title(title)
        self.geometry("780x560")
        self.minsize(560, 360)
        self.resizable(True, True)
        self.transient(parent)
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        body = ttk.Frame(self, padding=12)
        body.grid(row=0, column=0, sticky="nsew")
        body.columnconfigure(0, weight=1)
        body.rowconfigure(0, weight=1)
        text = tk.Text(body, wrap="word", background=COLORS["panel"], foreground=COLORS["text"],
                       insertbackground=COLORS["text"], relief="flat", padx=10, pady=10)
        vertical = ttk.Scrollbar(body, orient="vertical", command=text.yview)
        horizontal = ttk.Scrollbar(body, orient="horizontal", command=text.xview)
        text.configure(yscrollcommand=vertical.set, xscrollcommand=horizontal.set)
        text.grid(row=0, column=0, sticky="nsew")
        vertical.grid(row=0, column=1, sticky="ns")
        horizontal.grid(row=1, column=0, sticky="ew")
        text.insert("1.0", content)
        text.configure(state="disabled")
        ttk.Button(self, text="Close", command=self.destroy).grid(row=1, column=0, sticky="e", padx=12, pady=(0, 12))
        self.text = text


def labeled_entry(parent, label: str, variable: tk.Variable, row: int) -> ttk.Entry:
    ttk.Label(parent, text=label, style="Panel.TLabel").grid(row=row, column=0, sticky="w", padx=(0, 12), pady=6)
    entry = ttk.Entry(parent, textvariable=variable)
    entry.grid(row=row, column=1, sticky="ew", pady=6)
    return entry
