# -*- coding: utf-8 -*-
"""
Processing algorithms to manage connection presets (ArrayStorage, Datasphere, NetworkStore).
"""

from __future__ import annotations


from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (
    QgsProcessingAlgorithm,
    QgsProcessingException,
    QgsProcessingParameterString,
)

from .arraystorage_settings import ArrayStorageSettingsStore
from .datasphere_settings import DatasphereSettingsStore
from .network_store_settings import NetworkStoreSettingsStore


class _BaseSettingsAlgorithm(QgsProcessingAlgorithm):
    def createInstance(self):
        return self.__class__()

    def tr(self, string: str) -> str:
        return QCoreApplication.translate("Processing", string)

    def groupId(self) -> str:
        return "Settings"

    def group(self) -> str:
        return self.tr("Settings")

    def icon(self):
        # default gear icon from Qt
        return QIcon.fromTheme("preferences-system")

    def name_param(self):
        return QgsProcessingParameterString(
            "CFG_NAME",
            self.tr("Configuration name"),
        )


class ArrayStorageSaveConfigAlgorithm(_BaseSettingsAlgorithm):
    PARAM_BASE_URL = "BASE_URL"
    PARAM_STORE_ID = "STORE_ID"
    PARAM_USER = "USER"
    PARAM_PASS = "PASS"

    def name(self):
        return "arraystorage_save_config"

    def displayName(self):
        return self.tr("Save ArrayStorage Config")

    def shortHelpString(self):
        return self.tr("Save or update an ArrayStorage connection preset.")

    def initAlgorithm(self, config):
        self.addParameter(self.name_param())
        self.addParameter(
            QgsProcessingParameterString(
                self.PARAM_BASE_URL,
                self.tr("Base URL"),
                defaultValue="http://localhost:8013",
            )
        )
        self.addParameter(
            QgsProcessingParameterString(
                self.PARAM_STORE_ID,
                self.tr("Store ID (optional)"),
                optional=True,
            )
        )
        self.addParameter(
            QgsProcessingParameterString(
                self.PARAM_USER,
                self.tr("Username (optional)"),
                optional=True,
            )
        )
        self.addParameter(
            QgsProcessingParameterString(
                self.PARAM_PASS,
                self.tr("Password (optional)"),
                optional=True,
            )
        )

    def processAlgorithm(self, parameters, context, feedback):
        name = self.parameterAsString(parameters, "CFG_NAME", context)
        base_url = self.parameterAsString(parameters, self.PARAM_BASE_URL, context)
        store_id = self.parameterAsString(parameters, self.PARAM_STORE_ID, context)
        user = self.parameterAsString(parameters, self.PARAM_USER, context)
        pwd = self.parameterAsString(parameters, self.PARAM_PASS, context)

        store = ArrayStorageSettingsStore()
        cfg = store.add_or_update(name, base_url, store_id, user or None, pwd or None)

        return {"CFG_NAME": cfg.name}


class ArrayStorageDeleteConfigAlgorithm(_BaseSettingsAlgorithm):
    def name(self):
        return "arraystorage_delete_config"

    def displayName(self):
        return self.tr("Delete ArrayStorage Config")

    def shortHelpString(self):
        return self.tr("Delete an ArrayStorage connection preset by name.")

    def initAlgorithm(self, config):
        self.addParameter(self.name_param())

    def processAlgorithm(self, parameters, context, feedback):
        name = self.parameterAsString(parameters, "CFG_NAME", context)
        store = ArrayStorageSettingsStore()
        ok = store.delete(name)
        if not ok:
            names = ", ".join([c.name for c in store.list()])
            raise QgsProcessingException(
                f"Config '{name}' not found. Existing: {names or 'none'}."
            )
        return {"CFG_NAME": name}


class DatasphereSaveConfigAlgorithm(_BaseSettingsAlgorithm):
    PARAM_BASE_URL = "BASE_URL"
    PARAM_DS_ID = "DS_ID"
    PARAM_USER = "USER"
    PARAM_PASS = "PASS"

    def name(self):
        return "datasphere_save_config"

    def displayName(self):
        return self.tr("Save Datasphere Config")

    def shortHelpString(self):
        return self.tr("Save or update a Datasphere connection preset.")

    def initAlgorithm(self, config):
        self.addParameter(self.name_param())
        self.addParameter(
            QgsProcessingParameterString(
                self.PARAM_BASE_URL,
                self.tr("Base URL"),
                defaultValue="https://na.datasphere.online/external",
            )
        )
        self.addParameter(
            QgsProcessingParameterString(
                self.PARAM_DS_ID,
                self.tr("Datasource ID"),
                defaultValue="0",
            )
        )
        self.addParameter(
            QgsProcessingParameterString(
                self.PARAM_USER,
                self.tr("Username (optional)"),
                optional=True,
            )
        )
        self.addParameter(
            QgsProcessingParameterString(
                self.PARAM_PASS,
                self.tr("Password (optional)"),
                optional=True,
            )
        )

    def processAlgorithm(self, parameters, context, feedback):
        name = self.parameterAsString(parameters, "CFG_NAME", context)
        base_url = self.parameterAsString(parameters, self.PARAM_BASE_URL, context)
        ds_id = self.parameterAsString(parameters, self.PARAM_DS_ID, context)
        user = self.parameterAsString(parameters, self.PARAM_USER, context)
        pwd = self.parameterAsString(parameters, self.PARAM_PASS, context)

        store = DatasphereSettingsStore()
        cfg = store.add_or_update(name, base_url, ds_id, user or None, pwd or None)

        return {"CFG_NAME": cfg.name}


class DatasphereDeleteConfigAlgorithm(_BaseSettingsAlgorithm):
    def name(self):
        return "datasphere_delete_config"

    def displayName(self):
        return self.tr("Delete Datasphere Config")

    def shortHelpString(self):
        return self.tr("Delete a Datasphere connection preset by name.")

    def initAlgorithm(self, config):
        self.addParameter(self.name_param())

    def processAlgorithm(self, parameters, context, feedback):
        name = self.parameterAsString(parameters, "CFG_NAME", context)
        store = DatasphereSettingsStore()
        ok = store.delete(name)
        if not ok:
            names = ", ".join([c.name for c in store.list()])
            raise QgsProcessingException(
                f"Config '{name}' not found. Existing: {names or 'none'}."
            )
        return {"CFG_NAME": name}


class NetworkStoreSaveConfigAlgorithm(_BaseSettingsAlgorithm):
    PARAM_BASE_URL = "BASE_URL"
    PARAM_USER = "USER"
    PARAM_PASS = "PASS"

    def name(self):
        return "networkstore_save_config"

    def displayName(self):
        return self.tr("Save NetworkStore Config")

    def shortHelpString(self):
        return self.tr("Save or update a NetworkStore connection preset.")

    def initAlgorithm(self, config):
        self.addParameter(self.name_param())
        self.addParameter(
            QgsProcessingParameterString(
                self.PARAM_BASE_URL,
                self.tr("Base URL"),
                defaultValue="http://localhost:8013",
            )
        )
        self.addParameter(
            QgsProcessingParameterString(
                self.PARAM_USER,
                self.tr("Username (optional)"),
                optional=True,
            )
        )
        self.addParameter(
            QgsProcessingParameterString(
                self.PARAM_PASS,
                self.tr("Password (optional)"),
                optional=True,
            )
        )

    def processAlgorithm(self, parameters, context, feedback):
        name = self.parameterAsString(parameters, "CFG_NAME", context)
        base_url = self.parameterAsString(parameters, self.PARAM_BASE_URL, context)
        user = self.parameterAsString(parameters, self.PARAM_USER, context)
        pwd = self.parameterAsString(parameters, self.PARAM_PASS, context)

        store = NetworkStoreSettingsStore()
        cfg = store.add_or_update(name, base_url, user or None, pwd or None)

        return {"CFG_NAME": cfg.name}


class NetworkStoreDeleteConfigAlgorithm(_BaseSettingsAlgorithm):
    def name(self):
        return "networkstore_delete_config"

    def displayName(self):
        return self.tr("Delete NetworkStore Config")

    def shortHelpString(self):
        return self.tr("Delete a NetworkStore connection preset by name.")

    def initAlgorithm(self, config):
        self.addParameter(self.name_param())

    def processAlgorithm(self, parameters, context, feedback):
        name = self.parameterAsString(parameters, "CFG_NAME", context)
        store = NetworkStoreSettingsStore()
        ok = store.delete(name)
        if not ok:
            names = ", ".join([c.name for c in store.list()])
            raise QgsProcessingException(
                f"Config '{name}' not found. Existing: {names or 'none'}."
            )
        return {"CFG_NAME": name}
