# -*- coding: utf-8 -*-
"""GEE LULC Toolkit - combined single-window interface.

All six tools presented as tabs in one window. Each tab hosts the original
tool dialog/dock as an embedded widget, so every method, GEE call, and file
operation is exactly the same as the standalone tools - only the container
changes. Session state (the in-memory GEE stack, AOI, admin hint, ...) is
shared across all tabs through one `self.state` dict.
"""

import os

from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import (
    QDialog, QVBoxLayout, QTabWidget, QWidget, QScrollArea,
    QPushButton, QMessageBox, QDockWidget,
)

from .dialogs.loader_dialog import LoaderDialog
from .dialogs.sampling_dialog import SamplingDialog
from .dialogs.labeling_dock import LabelingDock
from .dialogs.classify_dialog import ClassifyDialog
from .dialogs.signatures_dialog import SignaturesDialog

ICONS = os.path.join(os.path.dirname(__file__), "icons")


def _embed(dialog):
    """Return a scrollable QWidget hosting `dialog`'s content so it can be a
    resizable tab.

    The dialog keeps working normally (its methods, signals, and state are
    untouched). We strip its window chrome and, crucially, relax its minimum
    size and wrap it in a scroll area - otherwise the dialog's own large
    setMinimumSize() would stop the combined window from being made smaller
    (the "can't resize tabs 1/4/5/6" problem).
    """
    try:
        dialog.setWindowFlags(Qt.WindowType.Widget)
    except (AttributeError, TypeError):  # Qt/QGIS API compatibility
        pass
    try:
        # let the scroll area take over sizing
        dialog.setMinimumSize(0, 0)
    except (AttributeError, TypeError):  # Qt/QGIS API compatibility
        pass
    for attr in ("btn_close",):
        b = getattr(dialog, attr, None)
        if b is not None:
            b.hide()

    host = QWidget()
    lay = QVBoxLayout(host)
    lay.setContentsMargins(0, 0, 0, 0)
    scroll = QScrollArea()
    scroll.setWidgetResizable(True)
    scroll.setFrameShape(QScrollArea.Shape.NoFrame)
    scroll.setWidget(dialog)
    lay.addWidget(scroll)
    host._dialog = dialog          # keep a strong reference
    return host


class CombinedLulcDialog(QDialog):
    """Single window holding all six tools as tabs with shared state."""

    def __init__(self, iface, parent=None):
        super().__init__(parent)
        self.iface = iface
        self.setWindowTitle("GEE LULC Toolkit")
        # A proper top-level window: Qt.Window alone is not enough on
        # Windows, because a window that has an OWNER (a parent widget)
        # never gets its own taskbar button. The plugin therefore creates
        # this dialog with parent=None and keeps a strong reference to it,
        # which is what lets you alt-tab to it like the Print Layout window.
        self.setWindowFlags(Qt.WindowType.Window
                            | Qt.WindowType.WindowMinMaxButtonsHint
                            | Qt.WindowType.WindowCloseButtonHint)
        try:
            self.setWindowIcon(self._icon("icon.png"))
        except (AttributeError, TypeError):  # Qt API compatibility
            pass
        self.setMinimumSize(1000, 760)
        self.resize(1180, 880)

        # one shared session state for every tab
        self.state = {
            "stack": None, "aoi": None, "aoi_name": "", "scale": None,
            "band_names": [], "classified": None,
            "classified_layer_id": None, "report_summary": "",
            "admin_hint": {}, "aoi_geom_wgs84": None,
        }
        self._build()

    def _icon(self, name):
        p = os.path.join(ICONS, name)
        return QIcon(p) if os.path.exists(p) else QIcon()

    def _build(self):
        root = QVBoxLayout(self)
        root.setContentsMargins(6, 6, 6, 6)
        self.tabs = QTabWidget()
        self.tabs.setDocumentMode(True)
        root.addWidget(self.tabs)

        # Tab 1 - Load GEE data (shares state)
        self.t_loader = LoaderDialog(self.iface, self.state, self)
        self.tabs.addTab(_embed(self.t_loader), self._icon("tool1_load.png"),
                         "1. Load data")

        # Tab 2 - Create sample points
        self.t_sampling = SamplingDialog(self.iface, self, self.state)
        self.tabs.addTab(_embed(self.t_sampling),
                         self._icon("tool2_samples.png"),
                         "2. Sample points")

        # Tab 3 - Label points. LabelingDock is a QDockWidget. We embed the
        # dock itself as the tab content but strip its title bar and floating
        # features so it behaves like a plain panel (its inner widget - and
        # therefore all its buttons - stays intact).
        self.t_labeling = LabelingDock(self.iface, self)
        self.t_labeling.state = self.state
        if getattr(self.t_labeling, "btn_close", None) is not None:
            self.t_labeling.btn_close.hide()
        # no title bar, no float/close buttons - it is just a panel now
        self.t_labeling.setFeatures(QDockWidget.DockWidgetFeature.NoDockWidgetFeatures)
        self.t_labeling.setTitleBarWidget(QWidget())   # empty -> hides title
        lab_host = QWidget()
        lab_lay = QVBoxLayout(lab_host)
        lab_lay.setContentsMargins(0, 0, 0, 0)
        lab_scroll = QScrollArea()
        lab_scroll.setWidgetResizable(True)
        lab_scroll.setFrameShape(QScrollArea.Shape.NoFrame)
        lab_scroll.setWidget(self.t_labeling)          # embed the dock as-is
        lab_lay.addWidget(lab_scroll)
        self.tabs.addTab(lab_host, self._icon("tool3_label.png"),
                         "3. Label points")

        # Tab 4 - Classify & accuracy (shares state)
        self.t_classify = ClassifyDialog(self.iface, self.state, self)
        # let "Edit sample points" switch to the Label tab in-window
        self.t_classify.switch_to_labeling = (
            lambda: self.tabs.setCurrentIndex(2))
        self.tabs.addTab(_embed(self.t_classify),
                         self._icon("tool4_classify.png"),
                         "4. Classify")

        # Tab 5 - Signatures & separability (shares state)
        self.t_sign = SignaturesDialog(self.iface, self.state, self)
        self.tabs.addTab(_embed(self.t_sign),
                         self._icon("tool6_signatures.png"),
                         "5. Signatures")

        # Tab 6 - Map Layout embedded directly (options in-tab + Generate)
        from .adminmap_dialog import AdminMapDialog
        self.t_layout = AdminMapDialog(self.iface, self)
        # hide the dialog's own OK/Cancel - Tab 6 drives generation itself
        for attr in ("buttonBox", "bb", "btn_box"):
            b = getattr(self.t_layout, attr, None)
            if b is not None:
                b.hide()
        try:
            self.t_layout.setMinimumSize(0, 0)
        except (AttributeError, TypeError):  # Qt/QGIS API compatibility
            pass
        lay_host = QWidget()
        lay_v = QVBoxLayout(lay_host)
        lay_v.setContentsMargins(0, 0, 0, 0)
        lay_scroll = QScrollArea()
        lay_scroll.setWidgetResizable(True)
        lay_scroll.setFrameShape(QScrollArea.Shape.NoFrame)
        lay_scroll.setWidget(self.t_layout)
        lay_v.addWidget(lay_scroll, 1)
        btn_gen = QPushButton("Generate map")
        btn_gen.setMinimumHeight(40)
        btn_gen.setStyleSheet("font-weight: bold;")
        btn_gen.clicked.connect(self._generate_map)
        lay_v.addWidget(btn_gen)
        self.tabs.addTab(lay_host, self._icon("tool5_layout.png"),
                         "6. Map Layout")

        # prepare the layout options from state whenever this tab is shown
        self.tabs.currentChanged.connect(self._on_tab_changed)

    def _on_tab_changed(self, idx):
        # tab 5 (index 5) is Map Layout - refresh its preselection
        if idx == 5:
            try:
                from .lulc_adminmap import prepare_lulc_dialog
                prepare_lulc_dialog(self.iface, self.state, self.t_layout)
            except (ImportError, ModuleNotFoundError, RuntimeError):  # GEE/Import
                pass

    def _generate_map(self):
        from .lulc_adminmap import generate_lulc_map
        try:
            generate_lulc_map(self.iface, self.state, self.t_layout)
        except Exception as e:
            QMessageBox.critical(self, "Generate map", str(e))
