import unittest

import boto3

from moto import mock_aws


@mock_aws
class TestRdsTagging(unittest.TestCase):
    def setUp(self) -> None:
        self.rds = boto3.client("rds", region_name="us-west-2")
        self.rtapi = boto3.client("resourcegroupstaggingapi", region_name="us-west-2")
        self.resources_tagged = []
        self.resources_untagged = []
        for i in range(3):
            database = self.rds.create_db_instance(
                DBInstanceIdentifier=f"db-instance-{i}",
                Engine="postgres",
                DBInstanceClass="db.m1.small",
                CopyTagsToSnapshot=bool(i),
                Tags=[{"Key": "test", "Value": f"value-{i}"}] if i else [],
            ).get("DBInstance")
            snapshot = self.rds.create_db_snapshot(
                DBInstanceIdentifier=database["DBInstanceIdentifier"],
                DBSnapshotIdentifier=f"snapshot-{i}",
            ).get("DBSnapshot")
            group = self.resources_tagged if i else self.resources_untagged
            group.append(database["DBInstanceArn"])
            group.append(snapshot["DBSnapshotArn"])
        automated_snapshots = self.rds.describe_db_snapshots(
            Filters=[
                {
                    "Name": "db-instance-id",
                    "Values": ["db-instance-1", "db-instance-2"],
                },
                {"Name": "snapshot-type", "Values": ["automated"]},
            ],
        )["DBSnapshots"]
        for snapshot in automated_snapshots:
            self.resources_tagged.append(snapshot["DBSnapshotArn"])

    def test_get_resources_rds(self):
        def assert_response(response, expected_count, resource_type=None):
            results = response.get("ResourceTagMappingList", [])
            assert len(results) == expected_count
            for item in results:
                arn = item["ResourceARN"]
                assert arn in self.resources_tagged
                assert arn not in self.resources_untagged
                if resource_type:
                    assert f":{resource_type}:" in arn

        resp = self.rtapi.get_resources(ResourceTypeFilters=["rds"])
        assert_response(resp, 6)
        resp = self.rtapi.get_resources(ResourceTypeFilters=["rds:db"])
        assert_response(resp, 2, resource_type="db")
        resp = self.rtapi.get_resources(ResourceTypeFilters=["rds:snapshot"])
        assert_response(resp, 4, resource_type="snapshot")
        resp = self.rtapi.get_resources(
            TagFilters=[{"Key": "test", "Values": ["value-1"]}]
        )
        assert_response(resp, 3)

    def test_tag_resources_rds(self):
        # WHEN
        # we tag resources
        self.rtapi.tag_resources(
            ResourceARNList=self.resources_tagged,
            Tags={"key1": "value1", "key2": "value2"},
        )

        # THEN
        # we can retrieve the tags using the RDS API
        def get_tags(arn):
            return self.rds.list_tags_for_resource(ResourceName=arn)["TagList"]

        for arn in self.resources_tagged:
            assert {"Key": "key1", "Value": "value1"} in get_tags(arn)
            assert {"Key": "key2", "Value": "value2"} in get_tags(arn)
        for arn in self.resources_untagged:
            assert get_tags(arn) == []

    def test_untag_resources_rds(self):
        for arn in self.resources_tagged:
            self.rds.add_tags_to_resource(
                ResourceName=arn,
                Tags=[
                    {"Key": "key1", "Value": "value1"},
                    {"Key": "key2", "Value": "value2"},
                ],
            )

        response = self.rtapi.untag_resources(
            ResourceARNList=self.resources_tagged,
            TagKeys=["key2"],
        )

        assert response["FailedResourcesMap"] == {}

        def get_tags(arn):
            return self.rds.list_tags_for_resource(ResourceName=arn)["TagList"]

        for arn in self.resources_tagged:
            tags = get_tags(arn)
            assert {"Key": "key1", "Value": "value1"} in tags
            assert {"Key": "key2", "Value": "value2"} not in tags
