# -*- coding: utf-8 -*-
"""02viz - Geospatial Visualization Studio: main plugin class.

Toolbar + togglable studio dock. The dock hosts the chart studio
(engine selection, data binding, chart gallery); rendering engines are
loaded lazily so QGIS startup stays instant. No top-level QGIS menu.
"""
from __future__ import annotations

import os

from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QMessageBox, QToolBar
from qgis.core import QgsProject, QgsVectorLayer

try:  # Qt5: QtWidgets / Qt6: QtGui
    from qgis.PyQt.QtWidgets import QAction
except ImportError:  # pragma: no cover - QGIS 4 / Qt6
    from qgis.PyQt.QtGui import QAction

PLUGIN_NAME = "02viz"
PLUGIN_TITLE = "02viz - Geospatial Visualization Studio"


class O2VizPlugin:
    TOOLBAR_NAME = "02viz Toolbar"

    def __init__(self, iface):
        self.iface = iface
        self.plugin_dir = os.path.dirname(__file__)
        self.icon_dir = os.path.join(self.plugin_dir, "icons")

        self.actions: list[QAction] = []
        self.toolbar: QToolBar | None = None
        self._dock = None

    # ───────────────────────── QGIS lifecycle ─────────────────────────

    def initGui(self) -> None:
        self.toolbar = QToolBar(self.TOOLBAR_NAME)
        self.toolbar.setObjectName("O2VizToolbar")
        self.iface.addToolBar(self.toolbar)

        self.panel_action = self._add_action(
            os.path.join(self.icon_dir, "icon.png"),
            "02viz Studio",
            self._toggle_dock,
            checkable=True,
            status_tip="Open or close the 02viz visualization studio",
        )

    def unload(self) -> None:
        if self._dock:
            self.iface.removeDockWidget(self._dock)
            self._dock.deleteLater()
            self._dock = None
        if self.toolbar:
            for action in self.actions:
                self.toolbar.removeAction(action)
                action.setParent(None)
                action.deleteLater()
            self.actions.clear()
            # removeToolBar() only takes the bar out of the layout; it stays a
            # child of the main window until the deferred delete runs, so a
            # plugin reload could leave an orphan toolbar behind.
            self.iface.mainWindow().removeToolBar(self.toolbar)
            self.toolbar.setParent(None)
            self.toolbar.deleteLater()
            self.toolbar = None

    # ───────────────────────── Studio dock ─────────────────────────

    def _toggle_dock(self) -> None:
        if self._dock is None:
            try:
                from .dialogs.dock import StudioDockWidget

                self._dock = StudioDockWidget(self.iface, self.icon_dir, self.iface.mainWindow())
                self._dock.setObjectName("O2VizDock")
                self._dock.visibilityChanged.connect(self.panel_action.setChecked)
                self.iface.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self._dock)
            except Exception as exc:
                QMessageBox.critical(self.iface.mainWindow(), PLUGIN_TITLE,
                                     f"Could not create the studio panel:\n{exc}")
                self.panel_action.setChecked(False)
                return
            # addDockWidget() already makes a freshly created dock visible, so
            # the very first click must not immediately toggle it back to
            # hidden — just raise it and stop, the same click already opened it.
            self._dock.setVisible(True)
            self._dock.raise_()
            return
        self._dock.setVisible(not self._dock.isVisible())
        if self._dock.isVisible():
            self._dock.raise_()

    def smartmodeler_suggest_chart(self, layer_id: str) -> dict:
        """Reviewed SmartModeler bridge: render 02viz's offline suggestion.

        The bridge accepts only an exact live project-layer id. It exposes no
        file path, export, custom specification, engine code, or network input;
        SmartModeler calls it only after showing its own explicit approval card.
        Feature values stay inside 02viz/QGIS and are never returned.
        """
        project = QgsProject.instance()
        layer = project.mapLayer(layer_id) if project is not None else None
        if not isinstance(layer, QgsVectorLayer):
            return {"ok": False, "message": "The target vector layer is unavailable."}
        if self._dock is None:
            self._toggle_dock()
        if self._dock is None:
            return {"ok": False, "message": "The 02viz dock could not be opened."}
        self._dock.setVisible(True)
        self._dock.raise_()
        self._dock.layer_combo.setLayer(layer)
        self._dock._suggest_chart()
        if not getattr(self._dock, "_last_html", ""):
            return {"ok": False, "message": "No suitable chart could be generated."}
        return {"ok": True, "message": "02viz rendered a smart chart."}

    # ───────────────────────── Helpers ─────────────────────────

    def _add_action(self, icon_path, text, callback, *, add_to_toolbar=True,
                    checkable=False, status_tip=None) -> QAction:
        action = QAction(QIcon(icon_path), text, self.iface.mainWindow())
        action.triggered.connect(callback)
        action.setCheckable(checkable)
        if status_tip:
            action.setStatusTip(status_tip)
        if add_to_toolbar and self.toolbar:
            self.toolbar.addAction(action)
        self.actions.append(action)
        return action
