from __future__ import annotations

import tkinter as tk
from tkinter import ttk

from gui.adapters import filter_rows, format_timestamp
from gui.widgets import DataTable, Page


class ProcessesPage(Page):
    def __init__(self, parent, details_callback=None):
        super().__init__(parent, "Live Processes", "Process state reconstructed from current telemetry")
        self.details_callback = details_callback
        controls = ttk.Frame(self); controls.grid(row=2, column=0, sticky="ew", pady=(0, 10))
        self.search = tk.StringVar(); self.severity = tk.StringVar(value="All"); self.classification = tk.StringVar(value="All")
        ttk.Entry(controls, textvariable=self.search, width=34).pack(side="left")
        ttk.Combobox(controls, textvariable=self.severity, values=["All", "info", "low", "medium", "high", "critical"], state="readonly", width=12).pack(side="left", padx=8)
        ttk.Combobox(controls, textvariable=self.classification, values=["All", "Trusted", "Normal", "Watchlisted", "High risk", "Unknown"], state="readonly", width=14).pack(side="left")
        ttk.Button(controls, text="Apply filters", command=self._render).pack(side="left", padx=8)
        ttk.Button(controls, text="Process details", command=self._show_details).pack(side="right")
        self.table = DataTable(self, [("pid", "PID", 70), ("process", "Process Name", 160),
                                      ("classification", "Classification", 110), ("severity", "Severity", 90),
                                      ("first_seen", "First Seen", 150), ("last_seen", "Last Seen", 150),
                                      ("reason", "Rule / Reason", 220)])
        self.table.grid(row=3, column=0, sticky="nsew"); self.rowconfigure(3, weight=1); self.rows = []
        self.table.tree.bind("<Double-1>", lambda _event: self._show_details())

    def refresh(self, snapshot):
        rows = []
        for item in snapshot["processes"]:
            name = str(item.get("process_name") or "unknown"); severity = str(item.get("severity") or "info").lower()
            classification = {"TRUSTED": "Trusted", "NORMAL": "Normal", "WATCHLISTED": "Watchlisted",
                              "HIGH_RISK": "High risk", "UNKNOWN": "Unknown"}.get(str(item.get("classification") or "UNKNOWN").upper(), "Unknown")
            rows.append({**item, "pid": item.get("pid", ""), "process": name, "classification": classification,
                         "severity": severity, "first_seen": format_timestamp(item.get("timestamp")),
                         "last_seen": format_timestamp(item.get("timestamp")), "reason": item.get("classification_reason") or "Insufficient process context"})
        self.rows = rows; self._render()

    def _render(self):
        self.table.set_rows(filter_rows(self.rows, self.search.get(), severity=self.severity.get(), classification=self.classification.get()))

    def _show_details(self):
        selected = self.table.tree.selection()
        if not selected or self.details_callback is None:
            return
        pid = str(self.table.tree.set(selected[0], "pid"))
        process = next((item for item in self.rows if str(item.get("pid")) == pid), None)
        if process is not None:
            self.details_callback(process)
