from unittest import IsolatedAsyncioTestCase, TestCase

from aiohttp.test_utils import make_mocked_request
from heaobject.aws import AWSDesktopObject, S3StorageClass, S3ArchiveDetailState
from heaobject.data import AWSS3FileObject
from heaobject.root import Permission
from heaserver.service.db import awsservicelib
from botocore.exceptions import ClientError

import heaserver.service.db.aws
from heaserver.service.db.aws import S3ObjectPermissionContext, USE_SIMULATE_PRINCIPAL_POLICY_FOR_PERMISSIONS
from heaserver.service.testcase.mockaws import MockS3
from collections.abc import Sequence
from types import MethodType

class TestAWSServiceLib(TestCase):

    def test_handle_client_error_404(self):
        c = ClientError(error_response={'Error': {'Code': heaserver.service.db.aws.CLIENT_ERROR_404}}, operation_name='foo')
        self.assertEqual(404, awsservicelib.handle_client_error(c).status)

    def test_handle_client_error_no_such_bucket(self):
        c = ClientError(error_response={'Error': {'Code': heaserver.service.db.aws.CLIENT_ERROR_NO_SUCH_BUCKET}}, operation_name='foo')
        self.assertEqual(404, awsservicelib.handle_client_error(c).status)

    def test_handle_client_error_unknown(self):
        c = ClientError(error_response={'Error': {'Code': "It's wrecked"}},
                        operation_name='foo')
        self.assertEqual(500, awsservicelib.handle_client_error(c).status)


class TestArchiveStatus(IsolatedAsyncioTestCase):

    def setUp(self):
        self.request = make_mocked_request('GET', '/')
        self.request.app['HEA_db'] = MockS3(None)
        self.perm_context: S3ObjectPermissionContext = S3ObjectPermissionContext(self.request)

        async def mock_is_super_admin(self) -> bool:
            return False
        async def mock_simulate_perms(self, obj: AWSDesktopObject, actions: Sequence[str]) -> list[Permission]:
            return [Permission.VIEWER, Permission.EDITOR, Permission.DELETER]
        async def mock_is_account_owner(self) -> bool:
            return False
        self.perm_context.is_super_admin = MethodType(mock_is_super_admin, self.perm_context)
        self.perm_context._simulate_perms = MethodType(mock_simulate_perms, self.perm_context)
        self.perm_context.is_account_owner = MethodType(mock_is_account_owner, self.perm_context)

    async def test_handle_display_name_attribute_permissions_glacier_deep_archive(self):
        obj: AWSS3FileObject = AWSS3FileObject()
        obj.storage_class = S3StorageClass.DEEP_ARCHIVE
        obj.archive_detail_state = S3ArchiveDetailState.ARCHIVED
        obj.key = 'test_key'
        self.assertEqual([Permission.VIEWER] if USE_SIMULATE_PRINCIPAL_POLICY_FOR_PERMISSIONS else [Permission.VIEWER],
                         await self.perm_context.get_attribute_permissions(obj, 'display_name'))

    async def test_handle_display_name_attribute_permissions_glacier_instant_retrieval(self):
        obj: AWSS3FileObject = AWSS3FileObject()
        obj.storage_class = S3StorageClass.GLACIER_IR
        obj.archive_detail_state = S3ArchiveDetailState.NOT_ARCHIVED
        obj.key = 'test_key'
        self.assertCountEqual([Permission.VIEWER, Permission.EDITOR],
                              await self.perm_context.get_attribute_permissions(obj, 'display_name'))

    async def test_handle_display_name_attribute_permissions_standard(self):
        obj: AWSS3FileObject = AWSS3FileObject()
        obj.storage_class = S3StorageClass.STANDARD
        obj.key = 'test_key'
        self.assertCountEqual([Permission.VIEWER, Permission.EDITOR],
                              await self.perm_context.get_attribute_permissions(obj, 'display_name'))

    async def test_handle_display_name_attribute_permissions_unknown(self):
        obj: AWSS3FileObject = AWSS3FileObject()
        obj.key = 'test_key'
        self.assertCountEqual([Permission.VIEWER, Permission.EDITOR],
                              await self.perm_context.get_attribute_permissions(obj, 'display_name'))

    async def test_handle_display_name_attribute_permissions_restoring(self):
        obj: AWSS3FileObject = AWSS3FileObject()
        obj.key = 'test_key'
        obj.storage_class = S3StorageClass.DEEP_ARCHIVE
        obj.archive_detail_state = S3ArchiveDetailState.RESTORING
        self.assertEqual([Permission.VIEWER] if USE_SIMULATE_PRINCIPAL_POLICY_FOR_PERMISSIONS else [Permission.VIEWER],
                         await self.perm_context.get_attribute_permissions(obj, 'display_name'))

    async def test_handle_display_name_attribute_permissions_restored(self):
        obj: AWSS3FileObject = AWSS3FileObject()
        obj.key = 'test_key'
        obj.storage_class = S3StorageClass.DEEP_ARCHIVE
        obj.archive_detail_state = S3ArchiveDetailState.RESTORED
        self.assertCountEqual([Permission.VIEWER, Permission.EDITOR],
                              await self.perm_context.get_attribute_permissions(obj, 'display_name'))




