import sys
from typing import Callable
import urwid
import time
from .system_info import SystemReport, system_info
from auto_cpufreq.config.config import config
from enum import Enum


class ViewType(str, Enum):
    STATS = "Stats"
    MONITOR = "Monitor"
    LIVE = "Live"

    def __str__(self) -> str:
        return self.value


class SystemMonitor:
    def __init__(self, type: ViewType, suggestion: bool = False):
        self.type: ViewType = type
        self.title_header = urwid.Text(f"{type} Mode", align="center")
        self.header = urwid.Columns(
            [
                self.title_header,
            ]
        )

        # Create separate content walkers for left and right columns
        self.left_content = urwid.SimpleListWalker([])
        self.right_content = urwid.SimpleListWalker([])

        # Create listboxes for both columns
        self.left_listbox = urwid.ListBox(self.left_content)
        self.right_listbox = urwid.ListBox(self.right_content)

        # Create a columns widget with a vertical line (using box drawing character)
        self.columns = urwid.Columns(
            [
                ("weight", 1, self.left_listbox),
                (
                    "fixed",
                    1,
                    urwid.AttrMap(urwid.SolidFill("│"), "divider"),
                ),  # Vertical line # type: ignore
                ("weight", 1, self.right_listbox),
            ],
            dividechars=0,
        )

        self.footer = urwid.AttrMap(
            urwid.Text(
                "Press Q or Ctrl+C to quit | Use ↑↓ or PageUp/PageDown to scroll",
                align="center",
            ),
            "footer",
        )

        self.frame = urwid.Frame(
            body=self.columns,
            header=urwid.AttrMap(self.header, "header"),
            footer=self.footer,
        )

        palette = [
            ("header", "white", "dark blue"),
            ("footer", "white", "dark green"),
            ("body", "white", "default"),
            ("divider", "light gray", "default"),  # Style for the vertical line
        ]

        if suggestion:
            palette.append(("suggestion", "yellow", "default"))

        self.loop = urwid.MainLoop(
            self.frame, palette=palette, unhandled_input=self.handle_input
        )

        self.last_focus_left = 0
        self.last_focus_right = 0
        self.on_quit: Callable[[], None] | None = None
        self.suggestion = suggestion

    def update(self, loop: urwid.MainLoop, user_data: dict) -> None:
        # Store current focus positions
        if len(self.left_content) > 0:
            _, self.last_focus_left = self.left_listbox.get_focus()
            if self.last_focus_left is None:
                self.last_focus_left = 0
        if len(self.right_content) > 0:
            _, self.last_focus_right = self.right_listbox.get_focus()
            if self.last_focus_right is None:
                self.last_focus_right = 0

        current_time = time.strftime("%H:%M:%S")
        self.title_header.set_text(f"{self.type} Mode - {current_time}")

        report: SystemReport = system_info.generate_system_report()
        self.format_system_info(report)

        # Restore focus positions
        if len(self.left_content) > 0:
            self.left_listbox.set_focus(min(self.last_focus_left, len(self.left_content) - 1))  # type: ignore
        if len(self.right_content) > 0:
            self.right_listbox.set_focus(min(self.last_focus_right, len(self.right_content) - 1))  # type: ignore

        self.loop.set_alarm_in(2, self.update)  # type: ignore

    def handle_input(self, key):
        if key in ("q", "Q"):
            if self.on_quit:
                self.on_quit()
            raise urwid.ExitMainLoop()

    def format_system_info(self, report: SystemReport):
        self.left_content.clear()
        self.right_content.clear()

        # Helper function to create centered text
        def aligned_text(text: str) -> urwid.Text:
            return urwid.Text(text, align="left")

        # Left Column - System Info and CPU Stats
        self.left_content.extend(
            [
                urwid.AttrMap(aligned_text("System Information"), "header"),
                aligned_text(""),
                aligned_text(f"Linux distro: {report.distro_name} {report.distro_ver}"),
                aligned_text(f"Linux kernel: {report.kernel_version}"),
                aligned_text(f"Processor: {report.processor_model}"),
                aligned_text(f"Cores: {report.total_core}"),
                aligned_text(f"Architecture: {report.arch}"),
                aligned_text(f"Driver: {report.cpu_driver}"),
                aligned_text(""),
            ]
        )

        if config.has_config():
            self.left_content.append(
                aligned_text(f"Using settings defined in {config.path} file")
            )
            self.left_content.append(aligned_text(""))

        # CPU Stats
        self.left_content.extend(
            [
                urwid.AttrMap(aligned_text("Current CPU Stats"), "header"),
                aligned_text(""),
                aligned_text(f"CPU max frequency: {report.cpu_max_freq} MHz"),
                aligned_text(f"CPU min frequency: {report.cpu_min_freq} MHz"),
                aligned_text(""),
                aligned_text("Core    Usage   Temperature     Frequency"),
            ]
        )

        for core in report.cores_info:
            self.left_content.append(
                aligned_text(
                    f"CPU{core.id:<2}    {core.usage:>4.1f}%    {core.temperature:>6.0f} °C    {core.frequency:>6.0f} MHz"
                )
            )

        if report.cpu_fan_speed:
            self.left_content.append(aligned_text(""))
            self.left_content.append(
                aligned_text(f"CPU fan speed: {report.cpu_fan_speed} RPM")
            )

        # Right Column - Battery, Frequency Scaling, and System Stats
        if report.battery_info != None:
            self.right_content.extend(
                [
                    urwid.AttrMap(aligned_text("Battery Stats"), "header"),
                    aligned_text(""),
                    aligned_text(f"Battery status: {str(report.battery_info)}"),
                    aligned_text(
                        f"Battery percentage: {(str(report.battery_info.battery_level) + '%') if report.battery_info.battery_level != None else 'Unknown'}"
                    ),
                    aligned_text(
                        f'AC plugged: {("Yes" if report.battery_info.is_ac_plugged else "No") if report.battery_info.is_ac_plugged != None else "Unknown"}'
                    ),
                    aligned_text(
                        f'Charging start threshold: {report.battery_info.charging_start_threshold if report.battery_info.is_ac_plugged != None else "Unknown"}'
                    ),
                    aligned_text(
                        f'Charging stop threshold: {report.battery_info.charging_stop_threshold if report.battery_info.is_ac_plugged != None else "Unknown"}'
                    ),
                    aligned_text(""),
                ]
            )

        # CPU Frequency Scaling
        self.right_content.extend(
            [
                urwid.AttrMap(aligned_text("CPU Frequency Scaling"), "header"),
                aligned_text(""),
                aligned_text(
                    f'Setting to use: "{report.current_gov if report.current_gov != None else "Unknown"}" governor'
                ),
            ]
        )

        if (
            self.suggestion
            and report.current_gov != None
            and system_info.governor_suggestion() != report.current_gov
        ):
            self.right_content.append(
                urwid.AttrMap(
                    aligned_text(
                        f'Suggesting use of: "{system_info.governor_suggestion()}" governor'
                    ),
                    "suggestion",
                )
            )

        if report.current_epp:
            self.right_content.append(
                aligned_text(f"EPP setting: {report.current_epp}")
            )
        else:
            self.right_content.append(
                aligned_text("Not setting EPP (not supported by system)")
            )

        if report.current_epb:
            self.right_content.append(
                aligned_text(f'Setting to use: "{report.current_epb}" EPB')
            )

        self.right_content.append(aligned_text(""))

        # System Statistics
        self.right_content.extend(
            [
                urwid.AttrMap(aligned_text("System Statistics"), "header"),
                aligned_text(""),
                aligned_text(f"Total CPU usage: {report.cpu_usage:.1f} %"),
                aligned_text(f"Total system load: {report.load:.2f}"),
            ]
        )

        if report.cores_info:
            avg_temp = sum(core.temperature for core in report.cores_info) / len(
                report.cores_info
            )
            self.right_content.append(
                aligned_text(f"Average temp. of all cores: {avg_temp:.2f} °C")
            )

        if report.avg_load:
            load_status = "Load optimal" if report.load < 1.0 else "Load high"
            self.right_content.append(
                aligned_text(
                    f"{load_status} (load average: {report.avg_load[0]:.2f}, {report.avg_load[1]:.2f}, {report.avg_load[2]:.2f})"
                )
            )

        if report.cores_info:
            usage_status = "Optimal" if report.cpu_usage < 70 else "High"
            temp_status = "high" if avg_temp > 75 else "normal"  # type: ignore
            self.right_content.append(
                aligned_text(
                    f"{usage_status} total CPU usage: {report.cpu_usage:.1f}%, {temp_status} average core temp: {avg_temp:.1f}°C"  # type: ignore
                )
            )

        turbo_status: str
        if report.is_turbo_on[0] != None:
            turbo_status = "On" if report.is_turbo_on[0] else "Off"
        elif report.is_turbo_on[1] != None:
            turbo_status = (
                f"Auto mode {'enabled' if report.is_turbo_on[1] else 'disabled'}"
            )
        else:
            turbo_status = "Unknown"
        self.right_content.append(aligned_text(f"Setting turbo boost: {turbo_status}"))
        if (
            self.suggestion
            and report.is_turbo_on[0] != None
            and system_info.turbo_on_suggestion() != report.is_turbo_on[0]
        ):
            self.right_content.append(
                urwid.AttrMap(
                    aligned_text(
                        f'Suggesting to set turbo boost: {"on" if system_info.turbo_on_suggestion() else "off"}'
                    ),
                    "suggestion",
                )
            )

    def run(self, on_quit: Callable[[], None] | None = None):
        try:
            if on_quit:
                self.on_quit = on_quit
            self.loop.set_alarm_in(0, self.update)  # type: ignore
            self.loop.run()
        except KeyboardInterrupt:
            if on_quit:
                on_quit()
            sys.exit(0)
