"""
Main EMDS Plugin class for QGIS
"""

from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Optional
import os

from qgis.core import QgsProject

from .qt_compat import (
    QAction,
    QCoreApplication,
    QDesktopServices,
    QIcon,
    QPushButton,
    QSettings,
    QTimer,
    QTranslator,
    QUrl,
    Qt,
)

from .dock_widget import EMDSDockWidget
from .app_paths import ensure_workspace
from .debug_logger import debug, error
from .first_run_setup import ensure_update_repository, repair_engine_payload
from .update_checker import DEFAULT_DOWNLOAD_PAGE_URL, UpdateChecker, UpdateCheckResult


class EMDSPlugin:
    """Main plugin class for EMDS for QGIS"""

    UPDATE_CHECK_INTERVAL = timedelta(days=1)
    UPDATE_CHECK_SETTINGS_KEY = "EMDS/updateChecker/lastCheckedUtc"

    def __init__(self, iface):
        """Initialize the plugin

        Args:
            iface: QGIS interface object
        """
        self.iface = iface
        self.canvas = iface.mapCanvas()
        self.dock_widget: Optional[EMDSDockWidget] = None
        self.action: Optional[QAction] = None
        self.update_action: Optional[QAction] = None
        self.update_checker = UpdateChecker(Path(__file__).resolve().parent / "metadata.txt")
        self._loaded = False

    def initGui(self):
        """Initialize the GUI (called when plugin is loaded)"""
        self._loaded = True
        ensure_workspace()

        # Plugin Manager installs/updates re-extract the ZIP and strip Unix
        # execute bits (and macOS may quarantine the engines), so self-heal
        # on every load rather than only at first install.
        try:
            repair_engine_payload(Path(__file__).resolve().parent)
        except Exception as exc:
            error("Engine payload repair failed", {"error": str(exc)})

        # Create action with icon
        icon_path = os.path.join(os.path.dirname(__file__), "resources", "icon.png")
        icon = QIcon(icon_path) if os.path.exists(icon_path) else QIcon()

        # Create action
        self.action = QAction(icon, "Toggle EMDS Display", self.iface.mainWindow())
        self.action.triggered.connect(self.toggle_dock)

        self.update_action = QAction("Check for Updates", self.iface.mainWindow())
        self.update_action.triggered.connect(self.check_for_updates)

        # Add to menu and toolbar
        self.iface.addPluginToMenu("&EMDS", self.action)
        self.iface.addPluginToMenu("&EMDS", self.update_action)
        self.iface.addToolBarIcon(self.action)

        # Create dock widget
        self.dock_widget = EMDSDockWidget(self.iface)
        self.iface.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.dock_widget)

        # Connect signals
        self.dock_widget.item_selected.connect(self._on_item_selected)
        self.dock_widget.results_visibility_toggled.connect(self._on_visibility_toggled)

        QTimer.singleShot(1500, self._offer_update_repository_if_needed)
        QTimer.singleShot(5000, self._automatic_update_check_if_due)

    def unload(self):
        """Remove plugin menu items and dock widget (called when plugin is unloaded)"""
        self._loaded = False
        if self.dock_widget:
            self.iface.removeDockWidget(self.dock_widget)
            self.dock_widget = None

        if self.action:
            self.iface.removePluginMenu("&EMDS", self.action)
            self.iface.removeToolBarIcon(self.action)
            self.action = None

        if self.update_action:
            self.iface.removePluginMenu("&EMDS", self.update_action)
            self.update_action = None

    def toggle_dock(self):
        """Toggle visibility of dock widget"""
        if self.dock_widget:
            if self.dock_widget.isVisible():
                self.dock_widget.hide()
            else:
                self.dock_widget.show()

    def _on_item_selected(self, path: dict):
        """Handle item selection - update map layers"""
        # Implementation: When a workflow step is selected, show only its result layers
        workflow_id = path.get("workflow_id")
        if workflow_id:
            # TODO: Toggle visibility of layers based on workflow step
            pass

    def _on_visibility_toggled(self, layer_name: str, visible: bool):
        """Handle layer visibility toggle"""
        try:
            project = QgsProject.instance()
            for layer in project.mapLayers().values():
                if layer.name() == layer_name:
                    layer.setVisible(visible)
                    self.canvas.refresh()
                    break
        except Exception as e:
            self.iface.messageBar().pushMessage(
                "EMDS", f"Error toggling layer visibility: {str(e)}", 2
            )

    def _offer_update_repository_if_needed(self):
        """One-time offer to register the EMDS plugin repository so updates
        arrive through the QGIS Plugin Manager. Presence is re-checked on
        every load; the prompt itself is never repeated after a decline."""
        if not self._loaded:
            return
        try:
            ensure_update_repository(self.iface.mainWindow())
        except Exception as exc:
            error("Update repository check failed", {"error": str(exc)})

    def check_for_updates(self):
        """Manually check the EMDS release manifest for plugin updates."""
        result = self.update_checker.check()
        self._record_update_check_time()
        self._show_update_result(result, manual=True)

    def _automatic_update_check_if_due(self):
        """Run a quiet update check at most once per day."""
        if not self._loaded:
            return

        if not self._is_update_check_due():
            return

        result = self.update_checker.check()
        self._record_update_check_time()
        if result.update_available or result.status == "platform_unavailable":
            self._show_update_result(result, manual=False)
        elif result.status == "error":
            error("Automatic update check failed", {"message": result.message})

    def _is_update_check_due(self) -> bool:
        settings = QSettings()
        try:
            value = settings.value(self.UPDATE_CHECK_SETTINGS_KEY, "", type=str)
        except TypeError:
            value = settings.value(self.UPDATE_CHECK_SETTINGS_KEY, "") or ""
        if not value:
            return True

        try:
            last_checked = datetime.fromisoformat(value)
            if last_checked.tzinfo is None:
                last_checked = last_checked.replace(tzinfo=timezone.utc)
        except ValueError:
            return True

        return datetime.now(timezone.utc) - last_checked >= self.UPDATE_CHECK_INTERVAL

    def _record_update_check_time(self):
        QSettings().setValue(
            self.UPDATE_CHECK_SETTINGS_KEY,
            datetime.now(timezone.utc).isoformat(),
        )

    def _show_update_result(self, result: UpdateCheckResult, manual: bool):
        debug(
            "Update check result",
            {
                "status": result.status,
                "current_version": result.current_version,
                "latest_version": result.latest_version,
                "platform": result.platform_id,
            },
        )

        if result.status == "current" and not manual:
            return

        if result.update_available:
            detail = (
                f"{result.message} Use QGIS Plugin Manager with the EMDS "
                f"{result.platform_id} repository, or download the ZIP from EMDS."
            )
            self._push_update_message(detail, result, level=0, duration=0 if manual else 20)
            return

        if result.status == "platform_unavailable":
            self._push_update_message(result.message, result, level=1, duration=0 if manual else 20)
            return

        level = 0 if result.status == "current" else 1
        duration = 8 if result.status == "current" else 12
        self.iface.messageBar().pushMessage("EMDS", result.message, level, duration)

    def _push_update_message(
        self,
        message: str,
        result: UpdateCheckResult,
        level: int,
        duration: int,
    ):
        try:
            item = self.iface.messageBar().createMessage("EMDS", message)
            open_button = QPushButton("Open Downloads")
            open_button.clicked.connect(
                lambda: self._open_url(
                    result.download_page_url
                    or result.zip_url
                    or result.repository_url
                    or DEFAULT_DOWNLOAD_PAGE_URL
                )
            )
            item.layout().addWidget(open_button)
            self.iface.messageBar().pushWidget(item, level, duration)
        except Exception as exc:
            error("Could not create update message bar item", {"error": str(exc)})
            self.iface.messageBar().pushMessage("EMDS", message, level, duration)

    def _open_url(self, url: str):
        QDesktopServices.openUrl(QUrl(url))
