# components/uart/uart_ui.py
# One-file UART page: dedicated handler + UI (no base_handler, no protocol_ui).

from PyQt6.QtWidgets import (
    QWidget,
    QVBoxLayout,
    QHBoxLayout,
    QPushButton,
    QComboBox,
    QLineEdit,
    QSplitter,
)
from PyQt6.QtCore import Qt

# project-local deps (unchanged)
from components.console.console_ui import console_widget
from components.console.console_registry import log_main_console
import components.items.elements as elements
from components.commands.command_table_ui import command_table_widget
import config.config as config

# UART logic + dialogs + db (unchanged)
from components.uart.uart_logic import UART_logic
from components.uart.uart_command_editor import UartCommandEditorDialog
from components.data import db


# -----------------------------
# Internal, dedicated UART handler
# -----------------------------
# -----------------------------
# Thin handler that calls back into the UI widget
# -----------------------------
class UartHandler:
    """
    Used by command_table_widget. It doesn't own UART logic.
    It just forwards actions to the parent UartWidget.
    """

    def __init__(self, widget: "UartWidget"):
        self.w = widget  # back-reference to the UI

    # table may request the list via the handler
    def get_command_list(self):
        return self.w.uart_logic.get_predefined_commands()

    # ----- actions triggered from the command table -----
    def send_command(self, command: dict):
        # command has "hex_string"
        self.w.send_command(command)

    # command editor ops (invoked from command table)
    def add_command(self):
        dialog = UartCommandEditorDialog()
        if dialog.exec():
            command = dialog.get_data()
            db.add_uart_command(command)

    def modify_command(self, command):
        dialog = UartCommandEditorDialog(command=command)
        if dialog.exec():
            updated_command = dialog.get_data()
            updated_command["id"] = command["id"]
            db.modify_uart_command(updated_command)

    def delete_command(self, command):
        db.delete_uart_command(command)


# -----------------------------
# UART UI (layout preserved)
# -----------------------------
class UartWidget(QWidget):
    """
    Drops in where your old ProtocolUIWidget(UART) was used.
    Same controls, same enable/disable behavior, same splitter/table/console layout.
    """

    def __init__(self, parent=None):
        super().__init__(parent)
        self.uart_logic = UART_logic()  # all comms live here
        self.handler = UartHandler(self)  # thin handler for table actions
        self.commands = self.uart_logic.get_predefined_commands()
        self.comboboxes = {}
        self.connection_status = False
        self.init_ui()

    def init_ui(self):
        # === Top Control Row ===
        top_controls = QWidget()
        top_controls_layout = QHBoxLayout(top_controls)
        top_controls_layout.setContentsMargins(0, 0, 0, 0)
        top_controls_layout.setSpacing(12)
        top_controls_layout.setAlignment(Qt.AlignmentFlag.AlignTop)

        # Dynamically create comboboxes based on handler configuration
        # Static definition instead of get_combobox_config()
        self.comboboxes["port"] = QComboBox()
        self.comboboxes["port"].addItems(self.uart_logic.get_channels())
        top_controls_layout.addWidget(
            elements.label_and_widget("Port", self.comboboxes["port"])
        )
        # Refresh button
        self.button_refresh = elements.create_icon_button(
            config.REFRESH_BUTTON_ICON_LINK, icon_size=30, border_size=4
        )
        top_controls_layout.addWidget(self.button_refresh)

        self.comboboxes["baudrate"] = QComboBox()
        self.comboboxes["baudrate"].addItems(self.uart_logic.get_baud_rates())
        top_controls_layout.addWidget(
            elements.label_and_widget("Baudrate", self.comboboxes["baudrate"])
        )

        self.comboboxes["data_bits"] = QComboBox()
        self.comboboxes["data_bits"].addItems(self.uart_logic.get_data_bits())
        top_controls_layout.addWidget(
            elements.label_and_widget("Data Bits", self.comboboxes["data_bits"])
        )

        self.comboboxes["stop_bits"] = QComboBox()
        self.comboboxes["stop_bits"].addItems(self.uart_logic.get_stop_bits())
        top_controls_layout.addWidget(
            elements.label_and_widget("Stop Bits", self.comboboxes["stop_bits"])
        )

        self.comboboxes["parity"] = QComboBox()
        self.comboboxes["parity"].addItems(self.uart_logic.get_parity())
        top_controls_layout.addWidget(
            elements.label_and_widget("Parity", self.comboboxes["parity"])
        )

        # Connect / Disconnect
        self.button_connect = QPushButton("Connect")
        top_controls_layout.addWidget(
            elements.label_and_widget("", self.button_connect)
        )

        self.button_disconnect = QPushButton("Disconnect")
        top_controls_layout.addWidget(
            elements.label_and_widget("", self.button_disconnect)
        )

        # === Command Table ===
        self.command_table = command_table_widget(
            commands=self.commands,
            handler=self.handler,  # table uses handler methods for send/CRUD
        )

        col1_widget = QWidget()
        col1_layout = QVBoxLayout(col1_widget)
        col1_layout.setContentsMargins(0, 0, 0, 0)
        col1_layout.setSpacing(4)
        col1_layout.addWidget(self.command_table)

        # === Input Field + Send Button ===
        self.input_hex = QLineEdit()
        self.button_send_raw = QPushButton("Send Raw")

        input_line_layout = QHBoxLayout()
        input_line_layout.setContentsMargins(0, 0, 0, 0)
        input_line_layout.setSpacing(4)
        input_line_layout.addWidget(self.input_hex)
        input_line_layout.addWidget(self.button_send_raw)

        # === Console ===
        self.console = console_widget()
        self.uart_logic.set_logger(self.console.log)

        console_stack_widget = QWidget()
        console_stack_layout = QVBoxLayout(console_stack_widget)
        console_stack_layout.setContentsMargins(0, 0, 0, 0)
        console_stack_layout.setSpacing(4)
        console_stack_layout.addLayout(input_line_layout)
        console_stack_layout.addWidget(self.console)

        # === Horizontal Splitter: Table | Console (sizes preserved) ===
        splitter = QSplitter(Qt.Orientation.Horizontal)
        splitter.addWidget(col1_widget)
        splitter.addWidget(console_stack_widget)
        splitter.setSizes([740, 1200])
        splitter.setStretchFactor(0, 0)
        splitter.setStretchFactor(1, 1)

        # === Main Layout ===
        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(4, 4, 4, 4)
        main_layout.setSpacing(6)
        main_layout.addWidget(top_controls)
        main_layout.addWidget(splitter, stretch=1)
        self.setLayout(main_layout)

        # === Signals ===
        self.button_refresh.clicked.connect(self.refresh)
        self.button_connect.clicked.connect(self.connect)
        self.button_disconnect.clicked.connect(self.disconnect)
        self.button_send_raw.clicked.connect(self.send_command_raw)

        self.disconnected_enable_status()

    # ---- UI state toggles (unchanged) ----
    def disconnected_enable_status(self):
        for combo in self.comboboxes.values():
            elements.set_enabled_state(True, combo, grayOut=False)

        elements.set_enabled_state(True, self.command_table, grayOut=False)
        elements.set_enabled_state(False, self.input_hex, grayOut=True)
        elements.set_enabled_state(False, self.button_send_raw, grayOut=True)
        elements.set_enabled_state(False, self.button_disconnect, grayOut=True)
        elements.set_enabled_state(True, self.button_connect, grayOut=False)

    def connected_enable_status(self):
        for combo in self.comboboxes.values():
            elements.set_enabled_state(False, combo, grayOut=True)

        elements.set_enabled_state(True, self.command_table, grayOut=False)
        elements.set_enabled_state(True, self.input_hex, grayOut=False)
        elements.set_enabled_state(True, self.button_send_raw, grayOut=False)
        elements.set_enabled_state(True, self.button_disconnect, grayOut=False)
        elements.set_enabled_state(False, self.button_connect, grayOut=True)

    # ---- Button handlers (unchanged behavior) ----
    def connect(self):
        log_main_console("info", "🔗 Connecting...")
        port = self.comboboxes["port"].currentText()
        baudrate = int(self.comboboxes["baudrate"].currentText())
        data_bits = int(self.comboboxes["data_bits"].currentText())
        stop_bits = float(self.comboboxes["stop_bits"].currentText())
        parity = self.comboboxes["parity"].currentText()[0].upper()
        success = self.uart_logic.connect(
            port=port,
            baudrate=baudrate,
            data_bits=data_bits,
            stop_bits=stop_bits,
            parity=parity,
        )
        if success:
            self.connected_enable_status()
            self.command_table.set_connected_state()
            self.connection_status = True
        else:
            elements.flash_button(
                self.button_connect, flash_style="background-color: red;"
            )

    def disconnect(self):
        log_main_console("info", "🔌 Disconnecting...")
        success = self.uart_logic.disconnect()
        if success:
            log_main_console("info", "🔌 Disconnecting...")
            self.disconnected_enable_status()
            self.command_table.set_disconnected_state()
            self.connection_status = False
            self.refresh(silent=True)
        else:
            elements.flash_button(
                self.button_disconnect, flash_style="background-color: red;"
            )

    def refresh(self, silent: bool = False):
        log_main_console("info", "🔄 Refreshing...")
        self.comboboxes["port"].clear()
        port = self.uart_logic.get_channels()
        if port:
            self.comboboxes["port"].addItems(port)
            if not silent:
                elements.flash_button(self.button_refresh)
            log_main_console("success", "🔄 Refresehd")
        else:
            elements.flash_button(
                self.button_refresh, flash_style="background-color: red;"
            )
            log_main_console("error", "🔄 Refresehd")

    def get_current_config(self):
        return {key: cb.currentText() for key, cb in self.comboboxes.items()}

    def send_command(self, command):
        # self.uart_logic.send_command(command["hex_string"])
        self.uart_logic.send_pgkomm2(command["hex_string"])
        config.CURRENT_COMMAND = command["name"]

    def send_command_raw(self):
        hex_str = self.input_hex.text().strip()
        if not hex_str:
            self.console.log("warning", "⚠️ No command entered.")
        else:
            self.uart_logic.send_command(hex_str)
            config.CURRENT_COMMAND = hex_str
