#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import pytest
import allure
from tests.api.volume import base
from configs import config
from lib.common.utils import data_utils
from lib import exceptions as lib_exc

CONF = config.CONF


class TestVolumesSnapshotNegativeJSON(base.BaseVolumeTest):
    """Negative tests of volume snapshot"""

    @classmethod
    def skip_checks(cls):
        super(TestVolumesSnapshotNegativeJSON, cls).skip_checks()
        if not CONF.volume_feature_enabled.snapshot:
            raise cls.skipException("Cinder volume snapshots are disabled")
        if not CONF.volume.volume_type_ssd and not CONF.volume.volume_type_hdd:
            raise cls.skipException("Only SSD or HDD type volume support snapshot")

    @pytest.mark.negative
    def test_create_snapshot_with_nonexistent_volume_id(self):
        """Test creating snapshot from non existent volume should fail

        :ref: `test_create_snapshot_with_nonexistent_volume_id <https://docs.openstack.org/tempest/latest/tests/volume/volume.html#volume.test_volumes_snapshots_negative.VolumesSnapshotNegativeTestJSON.test_create_snapshot_with_nonexistent_volume_id>`__
        """
        with allure.step(f"Create snapshot with non existent volume"):
            with pytest.raises(lib_exc.NotFound) as excinfo:
                s_name = data_utils.rand_name("snap")
                vol_id = data_utils.rand_uuid()
                self.create_snapshot(volume_id=vol_id, display_name=s_name)
        with allure.step("Verify the response error message"):
            assert f"Volume {vol_id} could not be found." in str(excinfo.value)

    @pytest.mark.negative
    def test_create_snapshot_without_passing_volume_id(self):
        """Test creating snapshot without passing volume_id should fail

        :ref: `test_create_snapshot_without_passing_volume_id <https://docs.openstack.org/tempest/latest/tests/volume/volume.html#volume.test_volumes_snapshots_negative.VolumesSnapshotNegativeTestJSON.test_create_snapshot_without_passing_volume_id>`__
        """
        # Create a snapshot without passing volume id
        with allure.step(f"Create snapshot without passing volume id"):
            with pytest.raises(lib_exc.NotFound) as excinfo:
                s_name = data_utils.rand_name("snap")
                self.create_snapshot(volume_id=None, display_name=s_name)
        with allure.step("Verify the response error message"):
            assert f"Volume {None} could not be found." in str(excinfo.value)

    @pytest.mark.negative
    def test_volume_from_snapshot_decreasing_size(self):
        """Test creating volume from snapshot with decreasing size

        creating volume from snapshot with decreasing size should fail.

        :ref: `test_volume_from_snapshot_decreasing_size <https://docs.openstack.org/tempest/latest/tests/volume/volume.html#volume.test_volumes_snapshots_negative.VolumesSnapshotNegativeTestJSON.test_volume_from_snapshot_decreasing_size>`__
        """
        # Creates a volume a snapshot passing a size different from the source
        src_size = CONF.volume.volume_size * 2
        with allure.step(f"Create snapshot from volume with size({src_size})"):
            src_vol = self.create_volume(size=src_size)
            src_snap = self.create_snapshot(src_vol["id"])

        # Destination volume smaller than source
        dest_size = CONF.volume.volume_size
        with allure.step(
            f"Create volume from snapshot with decreasing size({dest_size})"
        ):
            with pytest.raises(lib_exc.BadRequest) as excinfo:
                self.volumes_client.create_volume(
                    size=dest_size, snapshot_id=src_snap["id"]
                )
        with allure.step("Verify the response error message"):
            assert (
                f"Invalid input received: Volume size '{dest_size}'GB cannot be smaller than the snapshot size {src_size}GB."
                in str(excinfo.value)
            )

    @pytest.mark.negative
    def test_list_snapshot_invalid_param_limit(self):
        """Test listing snapshots with invalid limit param should fail

        :ref: `test_list_snapshot_invalid_param_limit <https://docs.openstack.org/tempest/latest/tests/volume/volume.html#volume.test_volumes_snapshots_negative.VolumesSnapshotNegativeTestJSON.test_list_snapshot_invalid_param_limit>`__
        """
        invalid_limit = "invalid"
        with allure.step(f"List snapshot with invalid limit param({invalid_limit})"):
            with pytest.raises(lib_exc.BadRequest) as excinfo:
                self.snapshots_client.list_snapshots(limit=invalid_limit)
        with allure.step("Verify the response error message"):
            assert "limit param must be an integer" in str(excinfo.value)

    @pytest.mark.negative
    def test_list_snapshots_invalid_param_sort(self):
        """Test listing snapshots with invalid sort key should fail

        :ref: `test_list_snapshots_invalid_param_sort <https://docs.openstack.org/tempest/latest/tests/volume/volume.html#volume.test_volumes_snapshots_negative.VolumesSnapshotNegativeTestJSON.test_list_snapshots_invalid_param_sort>`__
        """
        invalid_sort_key = "invalid"
        with allure.step(f"List snapshot with invalid sort key({invalid_sort_key})"):
            with pytest.raises(lib_exc.BadRequest) as excinfo:
                self.snapshots_client.list_snapshots(sort_key=invalid_sort_key)
        with allure.step("Verify the response error message"):
            assert "Invalid input received: Invalid sort key" in str(excinfo.value)

    @pytest.mark.negative
    def test_list_snapshots_invalid_param_marker(self):
        """Test listing snapshots with invalid marker should fail

        :ref: `test_list_snapshots_invalid_param_marker <https://docs.openstack.org/tempest/latest/tests/volume/volume.html#volume.test_volumes_snapshots_negative.VolumesSnapshotNegativeTestJSON.test_list_snapshots_invalid_param_marker>`__
        """
        invalid_marker = data_utils.rand_uuid()
        with allure.step(f"List snapshot with invalid marker({invalid_marker})"):
            with pytest.raises(lib_exc.NotFound) as excinfo:
                self.snapshots_client.list_snapshots(marker=invalid_marker)
        with allure.step("Verify the response error message"):
            assert f"Snapshot {invalid_marker} could not be found." in str(
                excinfo.value
            )
