import logging

from typing import Dict, Tuple, Optional

from saas.library.python.warden import warden_api, WardenFunctionality


class WardenManager:
    def __init__(self, component_name: str) -> None:
        self.component_name: str = component_name
        self._functionality_slug_to_info: Dict[str, Tuple[str, int]] = {}
        self._functionality_slug_to_visited: Dict[str, bool] = {}

        self._initialize()

    def _initialize(self) -> None:
        self._functionality_slug_to_info: Dict[str, Tuple[str, int]] = {}

        response_data: dict = warden_api.get_component(self.component_name)
        component: dict = response_data['component']

        for functionality in component['functionalityList']:
            slug: Optional[str] = functionality.get('slug')
            if slug and self._is_auto_functionality(slug):
                logging.debug('Loaded functionality %s with slug %s', functionality['id'], slug)
                self._functionality_slug_to_info[slug] = functionality['id'], 0

    @staticmethod
    def _is_auto_functionality(slug: str) -> bool:
        return slug.endswith('_auto')

    @staticmethod
    def _delete_functionality(functionality_id: str) -> None:
        warden_api.delete_functionality(functionality_id)

    def create_or_update_functionality(self, functionality: WardenFunctionality) -> None:
        info = self._functionality_slug_to_info.get(functionality.slug)
        self._functionality_slug_to_visited[functionality.slug] = True

        if info:
            functionality_id, updates_cnt = self._functionality_slug_to_info.get(functionality.slug)
            if updates_cnt >= 1:
                if functionality.test_flow:
                    logging.debug(
                        'Skipping update for functionality with slug %s, already updated',
                        functionality.slug
                    )
                    return
                else:
                    logging.error('Functionality with slug %s already was updated, '
                                  'the slug is probably not unique', functionality.slug)
                    raise ValueError

            logging.debug('Updating warden functionality %s with slug %s', functionality_id, functionality.slug)

            warden_api.update_functionality(functionality_id, functionality)
            self._functionality_slug_to_info[functionality.slug] = functionality_id, updates_cnt + 1
        else:
            logging.debug('Adding new functionality with slug %s', functionality.slug)

            result = warden_api.add_functionality(functionality)
            self._functionality_slug_to_info[functionality.slug] = result['functionalityId'], 1

    def delete_unvisited_functionalities(self) -> None:
        deleted_cnt = 0
        for slug, (id_, updates_cnt) in list(self._functionality_slug_to_info.items()):
            if self._functionality_slug_to_visited.get(slug):
                continue

            try:
                self._delete_functionality(id_)
            except:
                logging.exception('Unable to delete functionality with slug %s', slug)
            else:
                logging.debug('Deleting functionality with slug %s', slug)
                self._functionality_slug_to_info.pop(slug)
                self._functionality_slug_to_visited.pop(slug, None)
                deleted_cnt += 1

        logging.warning('Deleted %d unvisited warden functionalities', deleted_cnt)
