import logging
from typing import Union

from spaceone.core.service import *
from spaceone.core.error import *
from spaceone.dashboard.manager.public_folder_manager import PublicFolderManager
from spaceone.dashboard.manager.identity_manager import IdentityManager
from spaceone.dashboard.model.public_folder.request import *
from spaceone.dashboard.model.public_folder.response import *
from spaceone.dashboard.model.public_folder.database import PublicFolder

_LOGGER = logging.getLogger(__name__)


@authentication_handler
@authorization_handler
@mutation_handler
@event_handler
class PublicFolderService(BaseService):
    resource = "PublicFolder"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.pub_folder_mgr = PublicFolderManager()
        self.identity_mgr = IdentityManager()

    @transaction(
        permission="dashboard:PublicFolder.write",
        role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"],
    )
    @convert_model
    def create(self, params: PublicFolderCreateRequest) -> Union[PublicFolderResponse, dict]:
        """Create public folder

        Args:
            params (dict): {
                'name': 'str',                  # required
                'tags': 'dict',
                'dashboards': 'list',
                'resource_group': 'str',        # required
                'project_id': 'str',
                'workspace_id': 'str',          # injected from auth
                'domain_id': 'str'              # injected from auth (required)
            }

        Returns:
            PublicFolderResponse:
        """

        if params.resource_group == "PROJECT":
            if not params.project_id:
                raise ERROR_REQUIRED_PARAMETER(key="project_id")

            project_info = self.identity_mgr.get_project(params.project_id)
            params.workspace_id = project_info["workspace_id"]
        elif params.resource_group == "WORKSPACE":
            if not params.workspace_id:
                raise ERROR_REQUIRED_PARAMETER(key="workspace_id")

            self.identity_mgr.check_workspace(params.workspace_id, params.domain_id)
            params.project_id = "*"
        else:
            params.workspace_id = "*"
            params.project_id = "*"

        pub_folder_vo = self.pub_folder_mgr.create_public_folder(params.dict())

        # Create child dashboards
        if params.dashboards:
            pass

        return PublicFolderResponse(**pub_folder_vo.to_dict())

    @transaction(
        permission="dashboard:PublicFolder.write",
        role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"],
    )
    @convert_model
    def update(self, params: PublicFolderUpdateRequest) -> Union[PublicFolderResponse, dict]:
        """Update public folder

        Args:
            params (dict): {
                'folder_id': 'str',             # required
                'name': 'str',
                'tags': 'dict',
                'workspace_id': 'str',          # injected from auth
                'domain_id': 'str'              # injected from auth (required)
                'user_projects': 'list'         # injected from auth
            }

        Returns:
            PublicFolderResponse:
        """

        pub_folder_vo: PublicFolder = self.pub_folder_mgr.get_public_folder(
            params.folder_id, params.domain_id, params.workspace_id, params.user_projects
        )

        pub_folder_vo = self.pub_folder_mgr.update_public_folder_by_vo(
            params.dict(exclude_unset=True), pub_folder_vo)

        return PublicFolderResponse(**pub_folder_vo.to_dict())

    @transaction(
        permission="dashboard:PublicFolder.write",
        role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"],
    )
    @convert_model
    def delete(self, params: PublicFolderDeleteRequest) -> None:
        """Delete public folder

        Args:
            params (dict): {
                'folder_id': 'str',             # required
                'workspace_id': 'str',          # injected from auth
                'domain_id': 'str'              # injected from auth (required)
                'user_projects': 'list'         # injected from auth
            }

        Returns:
            None
        """

        pub_folder_vo: PublicFolder = self.pub_folder_mgr.get_public_folder(
            params.folder_id, params.domain_id, params.workspace_id, params.user_projects
        )

        self.pub_folder_mgr.delete_public_folder_by_vo(pub_folder_vo)

    @transaction(
        permission="dashboard:PublicFolder.read",
        role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"],
    )
    @convert_model
    def get(self, params: PublicFolderGetRequest) -> Union[PublicFolderResponse, dict]:
        """Get public folder

        Args:
            params (dict): {
                'folder_id': 'str',             # required
                'workspace_id': 'str',          # injected from auth
                'domain_id': 'str'              # injected from auth (required)
                'user_projects': 'list',        # injected from auth
            }

        Returns:
            PublicFolderResponse:
        """

        pub_folder_vo: PublicFolder = self.pub_folder_mgr.get_public_folder(
            params.folder_id, params.domain_id, params.workspace_id, params.user_projects
        )

        return PublicFolderResponse(**pub_folder_vo.to_dict())

    @transaction(
        permission="dashboard:PublicFolder.read",
        role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"],
    )
    @append_query_filter(
        ["folder_id", "name", "domain_id", "workspace_id", "project_id", "user_projects"]
    )
    @append_keyword_filter(["folder_id", "name"])
    @convert_model
    def list(self, params: PublicFolderSearchQueryRequest) -> Union[PublicFoldersResponse, dict]:
        """List public folders

        Args:
            params (dict): {
                'query': 'dict (spaceone.api.core.v1.Query)'
                'folder_id': 'str',
                'name': 'str',
                'project_id': 'str',
                'workspace_id': 'str',                          # injected from auth
                'domain_id': 'str',                             # injected from auth (required)
                'user_projects': 'list',                        # injected from auth
            }

        Returns:
            PublicFoldersResponse:
        """

        query = params.query or {}
        pub_folder_vos, total_count = self.pub_folder_mgr.list_public_folders(query)
        pub_dashboards_info = [pub_folder_vo.to_dict() for pub_folder_vo in pub_folder_vos]
        return PublicFoldersResponse(results=pub_dashboards_info, total_count=total_count)

    @transaction(
        permission="dashboard:PublicFolder.read",
        role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"],
    )
    @append_query_filter(["domain_id", "workspace_id", "user_projects"])
    @append_keyword_filter(["folder_id", "name"])
    @convert_model
    def stat(self, params: PublicFolderStatQueryRequest) -> dict:
        """
        Args:
            params (dict): {
                'query': 'dict (spaceone.api.core.v1.StatisticsQuery)'
                'workspace_id': 'str',                                  # injected from auth
                'domain_id': 'str'                                      # injected from auth (required)
                'user_projects': 'list',                                # injected from auth
            }

        Returns:
            dict:

        """

        query = params.query or {}
        return self.pub_folder_mgr.stat_public_folders(query)
