# -*- coding: utf-8 -*-
"""
/***************************************************************************
 NetworkStorePluginDialog
                                 A QGIS plugin
 export layers to kisters network store
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                             -------------------
        begin                : 2022-01-18
        git sha              : $Format:%H$
        copyright            : (C) 2022 by Attila Bibok
        email                : Attila.bibok@kisters.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""

import os

from qgis.gui import QgsFileWidget
from qgis.PyQt import uic
from qgis.PyQt import QtWidgets
from qgis.core import QgsProject, QgsLayerTreeNode

from .network_store_core import export_network

# This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer
FORM_CLASS_EXPORT, _ = uic.loadUiType(
    os.path.join(os.path.dirname(__file__), "network_store_dialog_export.ui")
)


class NetworkStorePluginDialogExport(QtWidgets.QDialog, FORM_CLASS_EXPORT):
    def __init__(self, parent=None):
        """Constructor."""
        super(NetworkStorePluginDialogExport, self).__init__(parent)
        # Set up the user interface from Designer through FORM_CLASS.
        # After self.setupUi() you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        # set filter for filename
        self.mQgsFileWidget_export.setFilter(
            "Network store JSON (*.json); GeoJSON (*.geojson)"
        )
        self.mQgsFileWidget_export.setStorageMode(QgsFileWidget.SaveFile)
        # Populate formats

        self.comboBoxFormat.addItem("JSON")
        self.comboBoxFormat.addItem("JSON (old format)")
        self.comboBoxFormat.addItem("geoJSON")

        self.comboBoxGroup.addItem("")
        root = QgsProject.instance().layerTreeRoot()

        for node in root.children():
            if node.nodeType() == QgsLayerTreeNode.NodeType.NodeGroup:
                subgroup_names = [
                    c.name()
                    for c in node.children()
                    if c.nodeType() == QgsLayerTreeNode.NodeType.NodeGroup
                ]
                # Require the standard subgroups AND that this group is a network-store one
                if {"Links", "Nodes"}.issubset(
                    subgroup_names
                ) and self._group_is_network_store(node):
                    self.comboBoxGroup.addItem(node.name())

    def _group_is_network_store(self, group_node: QgsLayerTreeNode) -> bool:
        """
        Return True if any layer inside this group (recursively) has
        the custom property 'network:id' set (non-empty).
        This identifies groups created/managed by the network-store plugin.
        """
        for child in group_node.children():
            if child.nodeType() == QgsLayerTreeNode.NodeType.NodeLayer:
                layer = child.layer()
                if layer is not None:
                    net_id = str(layer.customProperty("network:id", "")).strip()
                    if net_id:
                        return True
            elif child.nodeType() == QgsLayerTreeNode.NodeType.NodeGroup:
                if self._group_is_network_store(child):
                    return True
        return False

    def export_network(self) -> bool:
        """
        Collect current dialog state and call the core export_network()
        helper (shared with the Processing algorithm).
        """
        from urllib.parse import urlparse
        import os

        # 1) Target file
        target_file = (self.mQgsFileWidget_export.filePath() or "").strip()
        if not target_file:
            QtWidgets.QMessageBox.warning(
                self,
                self.tr("Missing output file"),
                self.tr("Please choose a target file to export to."),
            )
            return False

        # 2) Selected network group name
        group_name = (self.comboBoxGroup.currentText() or "").strip()
        if not group_name:
            QtWidgets.QMessageBox.warning(
                self,
                self.tr("Missing network"),
                self.tr("Please select a network group to export."),
            )
            return False

        # Find the corresponding group node in the layer tree
        root = QgsProject.instance().layerTreeRoot()
        group_node = None
        for node in root.children():
            if (
                node.nodeType() == QgsLayerTreeNode.NodeType.NodeGroup
                and node.name() == group_name
            ):
                group_node = node
                break

        if group_node is None:
            QtWidgets.QMessageBox.warning(
                self,
                self.tr("Group not found"),
                self.tr(f"Could not find group '{group_name}' in the layer tree."),
            )
            return False

        # 3) Walk layers under this group to recover network_id and base_url
        def _iter_layers(node):
            for child in node.children():
                if child.nodeType() == QgsLayerTreeNode.NodeType.NodeLayer:
                    lyr = child.layer()
                    if lyr is not None:
                        yield lyr
                elif child.nodeType() == QgsLayerTreeNode.NodeType.NodeGroup:
                    yield from _iter_layers(child)

        network_id = None
        base_url = None

        for lyr in _iter_layers(group_node):
            # network:id is set on all network-store layers
            net_id = str(lyr.customProperty("network:id", "")).strip()
            if net_id and network_id is None:
                network_id = net_id

            if base_url is None:
                # WFS HTTP URI we used when loading the network
                uri = lyr.source()
                parsed = urlparse(uri)
                base = f"{parsed.scheme}://{parsed.netloc}"
                path = parsed.path or ""
                idx = path.lower().find("/network-store")
                if idx != -1:
                    base += path[:idx]
                base_url = base.rstrip("/")

            if network_id and base_url:
                break

        if not network_id or not base_url:
            QtWidgets.QMessageBox.critical(
                self,
                self.tr("Export failed"),
                self.tr(
                    "Could not determine network ID and base URL from the selected group."
                ),
            )
            return False

        # 4) Determine export format from the target file extension
        ext = os.path.splitext(target_file)[1].lower()
        if ext == ".geojson":
            fmt_literal = "geojson"
        else:
            # default to new JSON format
            fmt_literal = "json"

        # 5) Call the shared core helper
        ok = export_network(base_url, network_id, fmt_literal, target_file)
        if not ok:
            QtWidgets.QMessageBox.critical(
                self,
                self.tr("Export failed"),
                self.tr("Exporting the network failed. Check the log for details."),
            )
            return False

        QtWidgets.QMessageBox.information(
            self,
            self.tr("Export complete"),
            self.tr(f"Network '{network_id}' exported to:\n{target_file}"),
        )
        return True
