"""IpcStackTab widget -- AI-LSC Stack Editor.

Drag ecosystem tools and skills into an ordered execution flow, validate
dependencies, and compile the runtime stack state to a JSON file.
"""

import json
import os
from datetime import datetime

from ai_lsc.ui.main_window import _atomic_write_json
from ai_lsc.constants import PIPELINE_FILE_NAME, STATE_FILE_NAME

try:
    from PySide6.QtCore import Qt
    from PySide6.QtWidgets import (
        QHBoxLayout,
        QLabel,
        QListWidget,
        QListWidgetItem,
        QPushButton,
        QTreeWidget,
        QTreeWidgetItem,
        QVBoxLayout,
        QWidget,
    )
    _HAS_QT = True
except ImportError:
    _HAS_QT = False

if _HAS_QT:

    class IpcStackTab(QWidget):
        """Visual stack flow compiler: drag ecosystem tools and skills
        into an ordered execution flow, validate dependencies, and compile
        the runtime stack state."""

        def __init__(self, main_window):
            super().__init__()
            self.main = main_window
            layout = QHBoxLayout(self)

            left_panel = QVBoxLayout()
            left_panel.addWidget(QLabel("<b>Available Ecosystem Components</b>"))
            self.avail_tree = QTreeWidget()
            self.avail_tree.setColumnCount(1)
            self.avail_tree.setHeaderLabels(["Component"])
            left_panel.addWidget(self.avail_tree)

            center_panel = QVBoxLayout()
            center_panel.addStretch()
            btn_add = QPushButton(" >> ")
            btn_add.clicked.connect(self.add_node)
            center_panel.addWidget(btn_add)
            btn_rem = QPushButton(" << ")
            btn_rem.clicked.connect(self.remove_node)
            center_panel.addWidget(btn_rem)
            center_panel.addStretch()

            right_panel = QVBoxLayout()
            right_panel.addWidget(QLabel("<b>Active Execution Flow</b>"))
            self.flow_list = QListWidget()
            right_panel.addWidget(self.flow_list)

            self.lbl_validation = QLabel("Health: Awaiting Compilation...")
            self.lbl_validation.setStyleSheet("color: #7f8c8d; font-weight: bold;")
            right_panel.addWidget(self.lbl_validation)

            btn_compile = QPushButton("Compile Stack")
            btn_compile.setStyleSheet(
                "background-color: #27ae60; padding: 10px; font-weight: bold;"
            )
            btn_compile.clicked.connect(self.compile_stack)
            right_panel.addWidget(btn_compile)

            layout.addLayout(left_panel, 2)
            layout.addLayout(center_panel, 1)
            layout.addLayout(right_panel, 2)

        def refresh(self):
            self.avail_tree.clear()
            state_file = os.path.join(self.main.config_root, STATE_FILE_NAME)
            installed_tools = []
            if os.path.exists(state_file):
                try:
                    with open(state_file) as f:
                        installed_tools = json.load(f).get("active_tools", [])
                except Exception:
                    pass

            if installed_tools:
                eco_node = QTreeWidgetItem(["Ecosystem Infrastructure"])
                self.avail_tree.addTopLevelItem(eco_node)
                for t_id in installed_tools:
                    meta = self.main.registry_mgr.get_tool(t_id)
                    item = QTreeWidgetItem([meta.get("name", t_id)])
                    item.setData(0, Qt.UserRole, t_id)
                    eco_node.addChild(item)

            skills_dir = self.main.skills_root
            if os.path.exists(skills_dir):
                skill_node = QTreeWidgetItem(["Runtime Skills"])
                self.avail_tree.addTopLevelItem(skill_node)
                for entry in sorted(os.listdir(skills_dir)):
                    if entry.startswith("."):
                        continue
                    full = os.path.join(skills_dir, entry)
                    if os.path.isfile(full):
                        item = QTreeWidgetItem([entry])
                        item.setData(0, Qt.UserRole, f"skill:{entry}")
                        skill_node.addChild(item)
            self.avail_tree.expandAll()

        def add_node(self):
            selected = self.avail_tree.currentItem()
            if not selected or not selected.data(0, Qt.UserRole):
                return
            t_id = selected.data(0, Qt.UserRole)
            display = selected.text(0)
            if t_id.startswith("skill:"):
                display = f"[Skill] {display}"

            existing = [
                self.flow_list.item(i).data(Qt.UserRole)
                for i in range(self.flow_list.count())
            ]
            if t_id in existing:
                return

            item = QListWidgetItem(display)
            item.setData(Qt.UserRole, t_id)
            self.flow_list.addItem(item)
            self.validate_flow()

        def remove_node(self):
            row = self.flow_list.currentRow()
            if row >= 0:
                self.flow_list.takeItem(row)
                self.validate_flow()

        def validate_flow(self):
            flow_ids = [
                self.flow_list.item(i).data(Qt.UserRole)
                for i in range(self.flow_list.count())
            ]
            missing = self.main.registry_mgr.check_dependencies(flow_ids)
            if missing:
                dep_names = [
                    self.main.registry_mgr.get_tool(d).get("name", d)
                    for d in missing
                ]
                self.lbl_validation.setText(
                    f"Warning: Missing Dependencies -> {', '.join(dep_names)}"
                )
                self.lbl_validation.setStyleSheet(
                    "color: #e74c3c; font-weight: bold;"
                )
            else:
                self.lbl_validation.setText(
                    "Health: Dependencies Satisfied. Ready to compile."
                )
                self.lbl_validation.setStyleSheet(
                    "color: #2ecc71; font-weight: bold;"
                )

        def compile_stack(self):
            flow_ids = [
                self.flow_list.item(i).data(Qt.UserRole)
                for i in range(self.flow_list.count())
            ]
            if not flow_ids:
                return

            port_map = {}
            for t_id in flow_ids:
                if t_id.startswith("skill:"):
                    continue
                meta = self.main.registry_mgr.get_tool(t_id)
                default_port = meta.get("launcher", {}).get("default_port")
                if default_port:
                    port_map[t_id] = default_port

            state = {
                "active_tools": flow_ids,
                "port_map": port_map,
                "timestamp": datetime.now().isoformat(),
            }
            pipe_file = os.path.join(self.main.config_root, PIPELINE_FILE_NAME)
            os.makedirs(self.main.config_root, exist_ok=True)
            _atomic_write_json(pipe_file, state)

            self.main.log(
                "Stack orchestration compiled successfully.", "StackCompiler"
            )
            self.main._populate_services()

else:
    IpcStackTab = None
