# SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors
#
# SPDX-License-Identifier: Apache-2.0


import collections.abc
import enum

from model.base import (
    ModelBase,
    NamedModelElement,
)


class DeliveryConfig(NamedModelElement):
    '''
    Not intended to be instantiated by users of this module
    '''
    def auth(self):
        return Auth(self.raw.get('auth'))

    def service(self):
        return DeliverySvcCfg(self.raw.get('service'))

    def dashboard(self):
        return DeliveryDashboardCfg(self.raw.get('dashboard'))

    def db_cfg_name(self):
        return self.raw.get('db_cfg_name')

    def _optional_attributes(self):
        yield from super()._optional_attributes()
        yield from [
            'db_cfg_name',
        ]

    def _required_attributes(self):
        yield from super()._required_attributes()
        yield from [
            'service',
        ]


class OAuthType(enum.Enum):
    GITHUB = 'github'


class Auth(ModelBase):
    def oauth_cfgs(self):
        return [OAuth(raw) for raw in self.raw.get('oauth_cfgs')]

    def oauth_cfg(self, github_cfg):
        for oc in self.oauth_cfgs():
            if oc.github_cfg() == github_cfg:
                return oc
        raise KeyError(f'no oauth cfg for {github_cfg}')


class OAuth(ModelBase):
    def name(self) -> str:
        return self.raw.get('name')

    def type(self):
        return OAuthType(self.raw.get('type'))

    def github_cfg(self):
        return self.raw.get('github_cfg')

    def oauth_url(self):
        return self.raw.get('oauth_url')

    def token_url(self):
        return self.raw.get('token_url')

    def client_id(self):
        return self.raw.get('client_id')

    def client_secret(self):
        return self.raw.get('client_secret')

    def scope(self):
        return self.raw.get('scope')


class SigningCfg(ModelBase):
    def id(self) -> str:
        return self.raw.get('id')

    def algorithm(self):
        return self.raw.get('algorithm', 'HS256')

    def secret(self):
        return self.raw.get('secret')

    def public_key(self):
        return self.raw.get('public_key')

    def purpose_labels(self) -> list[str]:
        return self.raw.get('purpose_labels', [])


class DeliveryDashboardCfg(ModelBase):
    def deployment_name(self):
        return self.raw.get('deployment_name', 'delivery-dashboard')


class DeliverySvcCfg(ModelBase):
    def deployment_name(self):
        return self.raw.get('deployment_name', 'delivery-service')

    def signing_cfgs(
        self,
        purpose_label: str = None,
    ) -> collections.abc.Generator[SigningCfg, None, None]:
        cfgs = self.raw.get('signing')

        if not purpose_label:
            yield from [
                SigningCfg(raw) for raw in cfgs
            ]
            return

        for raw_signing_cfg in cfgs:
            signing_cfg = SigningCfg(raw_signing_cfg)

            if purpose_label in signing_cfg.purpose_labels():
                yield signing_cfg


class DeliveryEndpointsCfg(NamedModelElement):
    def service_host(self):
        return self.raw['service_host']

    def base_url(self):
        return f'http://{self.service_host()}'

    def dashboard_host(self):
        return self.raw['dashboard_host']

    def dashboard_url(self):
        return f'https://{self.dashboard_host()}'
