#!/usr/bin/env python3
"""
Configure Interface Widget - vzug-e-hinge
==========================================
Manage interface profiles (UART/I2C configuration).
"""

from PyQt6.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QLabel,
    QLineEdit, QPushButton, QListWidget, QListWidgetItem,
    QMessageBox, QSplitter, QFormLayout, QSpinBox, QComboBox,
    QCheckBox, QScrollArea, QTabWidget
)
from PyQt6.QtCore import Qt, pyqtSignal
from database.init_database import DatabaseManager

try:
    from serial.tools import list_ports
    SERIAL_AVAILABLE = True
except ImportError:
    SERIAL_AVAILABLE = False

import os
import glob


# Standard UART settings
BAUD_RATES = ["9600", "19200", "38400", "57600", "115200", "230400", "256000" ,"460800", "921600"]
PARITY_OPTIONS = ["N", "E", "O", "M", "S"]


class ConfigureInterfaceWidget(QWidget):
    """Widget for managing interface profiles."""
    
    profile_saved = pyqtSignal(int)
    profile_deleted = pyqtSignal(int)
    
    def __init__(self, db_manager: DatabaseManager):
        super().__init__()
        self.db_manager = db_manager
        self.db_conn = db_manager.get_connection()
        self.current_profile_id = None
        self._init_ui()
        self._load_profiles()
    
    def _init_ui(self):
        """Initialize UI."""
        layout = QVBoxLayout()
        
        title = QLabel("Configure Interface Profiles")
        title.setStyleSheet("font-size: 16px; font-weight: bold;")
        layout.addWidget(title)
        
        splitter = QSplitter(Qt.Orientation.Horizontal)
        splitter.addWidget(self._create_list_panel())
        splitter.addWidget(self._create_editor_panel())
        splitter.setSizes([300, 700])
        
        layout.addWidget(splitter)
        self.setLayout(layout)
    
    def _create_list_panel(self):
        """Create profile list panel."""
        widget = QWidget()
        layout = QVBoxLayout()
        
        layout.addWidget(QLabel("Interface Profiles:"))
        
        self.profile_list = QListWidget()
        self.profile_list.currentItemChanged.connect(self._on_profile_selected)
        layout.addWidget(self.profile_list)
        
        btn_layout = QHBoxLayout()
        self.btn_add = QPushButton("Add New")
        self.btn_add.clicked.connect(self._on_add_clicked)
        btn_layout.addWidget(self.btn_add)
        
        self.btn_delete = QPushButton("Delete")
        self.btn_delete.clicked.connect(self._on_delete_clicked)
        self.btn_delete.setEnabled(False)
        btn_layout.addWidget(self.btn_delete)
        
        layout.addLayout(btn_layout)
        widget.setLayout(layout)
        return widget
    
    def _create_editor_panel(self):
        """Create editor panel with tabs."""
        widget = QWidget()
        layout = QVBoxLayout()
        
        name_layout = QHBoxLayout()
        name_layout.addWidget(QLabel("Profile Name:"))
        self.name_input = QLineEdit()
        self.name_input.textChanged.connect(self._enable_save)
        name_layout.addWidget(self.name_input)
        layout.addLayout(name_layout)
        
        self.tabs = QTabWidget()
        self.tabs.addTab(self._create_uart_command_tab(), "UART Command")
        self.tabs.addTab(self._create_uart_logger_tab(), "UART Logger")
        self.tabs.addTab(self._create_i2c_tab(), "I2C")
        layout.addWidget(self.tabs)
        
        btn_layout = QHBoxLayout()
        self.btn_save = QPushButton("Save Profile")
        self.btn_save.clicked.connect(self._on_save_clicked)
        self.btn_save.setEnabled(False)
        btn_layout.addWidget(self.btn_save)
        btn_layout.addStretch()
        
        layout.addLayout(btn_layout)
        widget.setLayout(layout)
        return widget
    
    def _create_uart_command_tab(self):
        """Create UART Command tab (no packet detection)."""
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        container = QWidget()
        layout = QVBoxLayout()
        
        uart_group = QGroupBox("UART Command Settings")
        form = QFormLayout()
        
        # Port with refresh
        port_layout = QHBoxLayout()
        self.cmd_port = QComboBox()
        self.cmd_port.setEditable(True)
        port_layout.addWidget(self.cmd_port)
        btn_refresh_cmd = QPushButton("🔄")
        btn_refresh_cmd.setMaximumWidth(40)
        btn_refresh_cmd.clicked.connect(lambda: self._refresh_uart_ports(self.cmd_port))
        port_layout.addWidget(btn_refresh_cmd)
        form.addRow("Port:", port_layout)
        
        self.cmd_baud = QComboBox()
        self.cmd_baud.addItems(BAUD_RATES)
        self.cmd_baud.setCurrentText("115200")
        form.addRow("Baud Rate:", self.cmd_baud)
        
        self.cmd_data_bits = QSpinBox()
        self.cmd_data_bits.setRange(5, 8)
        self.cmd_data_bits.setValue(8)
        form.addRow("Data Bits:", self.cmd_data_bits)
        
        self.cmd_stop_bits = QSpinBox()
        self.cmd_stop_bits.setRange(1, 2)
        self.cmd_stop_bits.setValue(1)
        form.addRow("Stop Bits:", self.cmd_stop_bits)
        
        self.cmd_parity = QComboBox()
        self.cmd_parity.addItems(PARITY_OPTIONS)
        form.addRow("Parity:", self.cmd_parity)
        
        self.cmd_timeout = QSpinBox()
        self.cmd_timeout.setRange(100, 10000)
        self.cmd_timeout.setValue(1000)
        self.cmd_timeout.setSuffix(" ms")
        form.addRow("Timeout:", self.cmd_timeout)
        
        uart_group.setLayout(form)
        layout.addWidget(uart_group)
        layout.addStretch()
        
        container.setLayout(layout)
        scroll.setWidget(container)
        
        # Initial port scan
        self._refresh_uart_ports(self.cmd_port)
        return scroll
    
    def _create_uart_logger_tab(self):
        """Create UART Logger tab (with packet detection)."""
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        container = QWidget()
        layout = QVBoxLayout()
        
        # Enable Logger checkbox
        self.logger_enable = QCheckBox("Enable UART Logger")
        self.logger_enable.setChecked(True)  # Default enabled
        self.logger_enable.setToolTip("Uncheck to skip logger port configuration (command port only)")
        self.logger_enable.stateChanged.connect(self._on_logger_enable_changed)
        layout.addWidget(self.logger_enable)
        
        uart_group = QGroupBox("UART Logger Settings")
        form = QFormLayout()
        
        # Port with refresh
        port_layout = QHBoxLayout()
        self.log_port = QComboBox()
        self.log_port.setEditable(True)
        port_layout.addWidget(self.log_port)
        btn_refresh_log = QPushButton("🔄")
        btn_refresh_log.setMaximumWidth(40)
        btn_refresh_log.clicked.connect(lambda: self._refresh_uart_ports(self.log_port))
        port_layout.addWidget(btn_refresh_log)
        form.addRow("Port:", port_layout)
        
        self.log_baud = QComboBox()
        self.log_baud.addItems(BAUD_RATES)
        self.log_baud.setCurrentText("115200")
        form.addRow("Baud Rate:", self.log_baud)
        
        self.log_data_bits = QSpinBox()
        self.log_data_bits.setRange(5, 8)
        self.log_data_bits.setValue(8)
        form.addRow("Data Bits:", self.log_data_bits)
        
        self.log_stop_bits = QSpinBox()
        self.log_stop_bits.setRange(1, 2)
        self.log_stop_bits.setValue(1)
        form.addRow("Stop Bits:", self.log_stop_bits)
        
        self.log_parity = QComboBox()
        self.log_parity.addItems(PARITY_OPTIONS)
        form.addRow("Parity:", self.log_parity)
        
        self.log_timeout = QSpinBox()
        self.log_timeout.setRange(100, 10000)
        self.log_timeout.setValue(1000)
        self.log_timeout.setSuffix(" ms")
        form.addRow("Timeout:", self.log_timeout)
        
        uart_group.setLayout(form)
        layout.addWidget(uart_group)
        
        # Packet Detection
        packet_group = QGroupBox("Packet Detection")
        packet_form = QFormLayout()
        
        self.packet_enable = QCheckBox("Enable Packet Detection")
        self.packet_enable.stateChanged.connect(self._enable_save)
        packet_form.addRow("", self.packet_enable)
        
        self.packet_start = QLineEdit("EF FE")
        packet_form.addRow("Start Marker:", self.packet_start)
        
        self.packet_length = QSpinBox()
        self.packet_length.setRange(1, 1024)
        self.packet_length.setValue(17)
        packet_form.addRow("Packet Length:", self.packet_length)
        
        self.packet_end = QLineEdit("EE")
        packet_form.addRow("End Marker:", self.packet_end)
        
        packet_group.setLayout(packet_form)
        layout.addWidget(packet_group)
        layout.addStretch()
        
        container.setLayout(layout)
        scroll.setWidget(container)
        
        # Initial port scan
        self._refresh_uart_ports(self.log_port)
        return scroll
    
    def _create_i2c_tab(self):
        """Create I2C tab."""
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        container = QWidget()
        layout = QVBoxLayout()
        
        i2c_group = QGroupBox("I2C Settings")
        form = QFormLayout()
        
        # Bus with refresh
        bus_layout = QHBoxLayout()
        self.i2c_bus = QComboBox()
        self.i2c_bus.setEditable(True)
        bus_layout.addWidget(self.i2c_bus)
        btn_refresh_i2c = QPushButton("🔄")
        btn_refresh_i2c.setMaximumWidth(40)
        btn_refresh_i2c.clicked.connect(self._refresh_i2c_buses)
        bus_layout.addWidget(btn_refresh_i2c)
        form.addRow("Bus:", bus_layout)
        
        self.i2c_address = QLineEdit("0x40")
        form.addRow("Slave Address:", self.i2c_address)
        
        self.i2c_register = QLineEdit("0xFE")
        form.addRow("Read Register:", self.i2c_register)
        
        self.i2c_length = QSpinBox()
        self.i2c_length.setRange(1, 256)
        self.i2c_length.setValue(2)
        form.addRow("Read Length:", self.i2c_length)
        
        i2c_group.setLayout(form)
        layout.addWidget(i2c_group)
        layout.addStretch()
        
        container.setLayout(layout)
        scroll.setWidget(container)
        
        # Initial bus scan
        self._refresh_i2c_buses()
        return scroll
    
    def _refresh_uart_ports(self, combo: QComboBox):
        """Refresh UART ports in combo box."""
        current = combo.currentText().split(' - ')[0] if combo.currentText() else None
        combo.clear()
        
        if SERIAL_AVAILABLE:
            ports = list_ports.comports()
            for port in ports:
                display = f"{port.device} - {port.description}"
                combo.addItem(display, port.device)
        else:
            # Fallback: scan /dev/tty*
            for pattern in ['/dev/ttyUSB*', '/dev/ttyACM*', '/dev/ttyS*']:
                for port in glob.glob(pattern):
                    combo.addItem(port, port)
        
        # Restore selection if exists
        if current:
            for i in range(combo.count()):
                if combo.itemData(i) == current:
                    combo.setCurrentIndex(i)
                    break
    
    def _refresh_i2c_buses(self):
        """Refresh I2C buses."""
        current = self.i2c_bus.currentText()
        self.i2c_bus.clear()
        
        # Scan for I2C buses
        for i in range(10):  # Check buses 0-9
            bus_path = f"/dev/i2c-{i}"
            if os.path.exists(bus_path):
                self.i2c_bus.addItem(str(i))
        
        # Restore selection
        if current:
            idx = self.i2c_bus.findText(current)
            if idx >= 0:
                self.i2c_bus.setCurrentIndex(idx)
    
    def _load_profiles(self):
        """Load profiles from database."""
        self.profile_list.clear()
        cursor = self.db_conn.execute(
            "SELECT profile_id, profile_name FROM interface_profiles ORDER BY profile_name"
        )
        for row in cursor.fetchall():
            item = QListWidgetItem(row[1])
            item.setData(Qt.ItemDataRole.UserRole, row[0])
            self.profile_list.addItem(item)
    
    def _load_profile_details(self, profile_id: int):
        """Load profile into editor."""
        cursor = self.db_conn.execute("""
            SELECT profile_name,
                   uart_command_port, uart_command_baud, uart_command_data_bits,
                   uart_command_stop_bits, uart_command_parity, uart_command_timeout_ms,
                   uart_logger_enable, uart_logger_port, uart_logger_baud, uart_logger_data_bits,
                   uart_logger_stop_bits, uart_logger_parity, uart_logger_timeout_ms,
                   uart_logger_packet_detect_enable, uart_logger_packet_detect_start,
                   uart_logger_packet_detect_length, uart_logger_packet_detect_end,
                   i2c_port, i2c_slave_address, i2c_slave_read_register, i2c_slave_read_length
            FROM interface_profiles WHERE profile_id = ?
        """, (profile_id,))
        
        row = cursor.fetchone()
        if row:
            self.name_input.setText(row[0] or "")
            
            # UART Command
            self._set_combo_value(self.cmd_port, row[1])
            self.cmd_baud.setCurrentText(str(row[2] or 115200))
            self.cmd_data_bits.setValue(row[3] or 8)
            self.cmd_stop_bits.setValue(row[4] or 1)
            self.cmd_parity.setCurrentText(row[5] or "N")
            self.cmd_timeout.setValue(row[6] or 1000)
            
            # UART Logger Enable
            logger_enabled = bool(row[7]) if row[7] is not None else True  # Default enabled
            self.logger_enable.setChecked(logger_enabled)
            
            # UART Logger
            self._set_combo_value(self.log_port, row[8])
            self.log_baud.setCurrentText(str(row[9] or 115200))
            self.log_data_bits.setValue(row[10] or 8)
            self.log_stop_bits.setValue(row[11] or 1)
            self.log_parity.setCurrentText(row[12] or "N")
            self.log_timeout.setValue(row[13] or 1000)
            
            # Packet detection
            self.packet_enable.setChecked(bool(row[14]))
            self.packet_start.setText(row[15] or "")
            self.packet_length.setValue(row[16] or 17)
            self.packet_end.setText(row[17] or "")
            
            # I2C
            self.i2c_bus.setCurrentText(row[18] or "")
            self.i2c_address.setText(row[19] or "")
            self.i2c_register.setText(row[20] or "")
            self.i2c_length.setValue(row[21] or 2)
            
            self.current_profile_id = profile_id
            self.btn_delete.setEnabled(True)
            self.btn_save.setEnabled(True)  # Always allow saving
    
    def _set_combo_value(self, combo: QComboBox, value: str):
        """Set combo value by matching device."""
        if not value:
            return
        for i in range(combo.count()):
            if combo.itemData(i) == value:
                combo.setCurrentIndex(i)
                return
        # Not found, set as text
        combo.setCurrentText(value)
    
    def _on_profile_selected(self, current, previous):
        """Handle profile selection."""
        if current:
            profile_id = current.data(Qt.ItemDataRole.UserRole)
            self._load_profile_details(profile_id)
    
    def _on_add_clicked(self):
        """Handle add button."""
        self.name_input.clear()
        self._refresh_uart_ports(self.cmd_port)
        self._refresh_uart_ports(self.log_port)
        self._refresh_i2c_buses()
        
        self.profile_list.clearSelection()
        self.current_profile_id = None
        self.btn_delete.setEnabled(False)
        self.btn_save.setEnabled(True)
        self.name_input.setFocus()
    
    def _on_delete_clicked(self):
        """Handle delete button."""
        if not self.current_profile_id:
            return
        
        reply = QMessageBox.question(
            self, "Confirm Delete",
            f"Delete profile '{self.name_input.text()}'?",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
        )
        if reply != QMessageBox.StandardButton.Yes:
            return
        
        try:
            self.db_conn.execute(
                "DELETE FROM interface_profiles WHERE profile_id = ?",
                (self.current_profile_id,)
            )
            self.db_conn.commit()
            self.profile_deleted.emit(self.current_profile_id)
            self._load_profiles()
            self.current_profile_id = None
            self.btn_save.setEnabled(False)
            self.btn_delete.setEnabled(False)
            QMessageBox.information(self, "Success", "Profile deleted")
        except Exception as e:
            QMessageBox.critical(self, "Error", f"Delete failed: {str(e)}")
    
    def _on_save_clicked(self):
        """Handle save button."""
        name = self.name_input.text().strip()
        if not name:
            QMessageBox.warning(self, "Error", "Profile name required")
            return
        
        # Get logger enable state
        logger_enabled = self.logger_enable.isChecked()
        
        # Validate: UART Command and UART Logger must use different ports (only if logger enabled)
        if logger_enabled:
            cmd_port = self.cmd_port.currentData() or self.cmd_port.currentText()
            log_port = self.log_port.currentData() or self.log_port.currentText()
            
            if cmd_port and log_port and cmd_port == log_port:
                QMessageBox.warning(
                    self, 
                    "Port Conflict", 
                    "UART Command and UART Logger cannot use the same port!\n\n"
                    f"Both are set to: {cmd_port}\n\n"
                    "Please select different ports."
                )
                return
        
        try:
            values = (
                name,
                self.cmd_port.currentData() or self.cmd_port.currentText(),
                int(self.cmd_baud.currentText()),
                self.cmd_data_bits.value(),
                self.cmd_stop_bits.value(),
                self.cmd_parity.currentText(),
                self.cmd_timeout.value(),
                int(logger_enabled),  # uart_logger_enable
                self.log_port.currentData() or self.log_port.currentText(),
                int(self.log_baud.currentText()),
                self.log_data_bits.value(),
                self.log_stop_bits.value(),
                self.log_parity.currentText(),
                self.log_timeout.value(),
                int(self.packet_enable.isChecked()),
                self.packet_start.text(),
                self.packet_length.value(),
                self.packet_end.text(),
                self.i2c_bus.currentText(),
                self.i2c_address.text(),
                self.i2c_register.text(),
                self.i2c_length.value()
            )
            
            if self.current_profile_id:
                self.db_conn.execute("""
                    UPDATE interface_profiles SET
                        profile_name=?, uart_command_port=?, uart_command_baud=?,
                        uart_command_data_bits=?, uart_command_stop_bits=?, uart_command_parity=?,
                        uart_command_timeout_ms=?, uart_logger_enable=?, uart_logger_port=?, uart_logger_baud=?,
                        uart_logger_data_bits=?, uart_logger_stop_bits=?, uart_logger_parity=?,
                        uart_logger_timeout_ms=?, uart_logger_packet_detect_enable=?,
                        uart_logger_packet_detect_start=?, uart_logger_packet_detect_length=?,
                        uart_logger_packet_detect_end=?, i2c_port=?, i2c_slave_address=?,
                        i2c_slave_read_register=?, i2c_slave_read_length=?,
                        last_modified=datetime('now')
                    WHERE profile_id=?
                """, values + (self.current_profile_id,))
                msg = "Profile updated"
            else:
                cursor = self.db_conn.execute("""
                    INSERT INTO interface_profiles (
                        profile_name, uart_command_port, uart_command_baud,
                        uart_command_data_bits, uart_command_stop_bits, uart_command_parity,
                        uart_command_timeout_ms, uart_logger_enable, uart_logger_port, uart_logger_baud,
                        uart_logger_data_bits, uart_logger_stop_bits, uart_logger_parity,
                        uart_logger_timeout_ms, uart_logger_packet_detect_enable,
                        uart_logger_packet_detect_start, uart_logger_packet_detect_length,
                        uart_logger_packet_detect_end, i2c_port, i2c_slave_address,
                        i2c_slave_read_register, i2c_slave_read_length
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                """, values)
                self.current_profile_id = cursor.lastrowid
                msg = "Profile created"
            
            self.db_conn.commit()
            self.profile_saved.emit(self.current_profile_id)
            self._load_profiles()
            QMessageBox.information(self, "Success", msg)
            self.btn_save.setEnabled(False)
        except Exception as e:
            QMessageBox.critical(self, "Error", f"Save failed: {str(e)}")
    
    def _on_logger_enable_changed(self, state):
        """Handle logger enable checkbox change."""
        enabled = (state == Qt.CheckState.Checked.value)
        
        # Enable/disable all logger fields
        self.log_port.setEnabled(enabled)
        self.log_baud.setEnabled(enabled)
        self.log_data_bits.setEnabled(enabled)
        self.log_stop_bits.setEnabled(enabled)
        self.log_parity.setEnabled(enabled)
        self.log_timeout.setEnabled(enabled)
        
        # Enable/disable packet detection
        self.packet_enable.setEnabled(enabled)
        self.packet_start.setEnabled(enabled)
        self.packet_length.setEnabled(enabled)
        self.packet_end.setEnabled(enabled)
        
        self._enable_save()
    
    def _enable_save(self):
        """Enable save button."""
        self.btn_save.setEnabled(True)


if __name__ == "__main__":
    import sys
    from PyQt6.QtWidgets import QApplication
    
    app = QApplication(sys.argv)
    db = DatabaseManager("database/ehinge.db")
    db.initialize()
    
    widget = ConfigureInterfaceWidget(db)
    widget.setWindowTitle("Configure Interface Profiles")
    widget.resize(1000, 600)
    widget.show()
    
    sys.exit(app.exec())
