"""Unit tests for scripts/untag_acdl_keys.py key-list logic (REQ-162, P3).

Tests the pure ``acdl_keys_in()`` + ``keys_to_untag()`` functions (the AWS
I/O glue is thin boto3 around them). The script does not need live AWS to
be importable.
"""

import sys
from pathlib import Path

import pytest

sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "scripts"))

from untag_acdl_keys import acdl_keys_in, keys_to_untag, DEFAULT_LEGACY_KEYS  # noqa: E402


class TestAcdlKeysIn:
    def test_empty(self):
        assert acdl_keys_in([]) == []

    def test_no_acdl_keys(self):
        assert acdl_keys_in(["nova:owner", "nova:contract", "Name"]) == []

    def test_all_acdl_keys(self):
        keys = ["acdl:owner", "acdl:contract", "acdl:environment", "acdl:cost-center", "acdl:ref"]
        assert acdl_keys_in(keys) == list(keys)

    def test_mixed_keys(self):
        keys = ["acdl:owner", "nova:owner", "Name", "acdl:cost-center"]
        assert acdl_keys_in(keys) == ["acdl:owner", "acdl:cost-center"]

    def test_preserves_input_order(self):
        keys = ["acdl:ref", "nova:owner", "acdl:owner", "acdl:contract"]
        assert acdl_keys_in(keys) == ["acdl:ref", "acdl:owner", "acdl:contract"]

    def test_custom_legacy_set(self):
        # Only removing acdl:owner + acdl:ref (subset)
        legacy = ("acdl:owner", "acdl:ref")
        keys = ["acdl:owner", "acdl:contract", "acdl:ref", "nova:owner"]
        assert acdl_keys_in(keys, legacy_keys=legacy) == ["acdl:owner", "acdl:ref"]

    def test_default_legacy_keys_all_5(self):
        assert len(DEFAULT_LEGACY_KEYS) == 5
        assert "acdl:owner" in DEFAULT_LEGACY_KEYS
        assert "acdl:contract" in DEFAULT_LEGACY_KEYS
        assert "acdl:environment" in DEFAULT_LEGACY_KEYS
        assert "acdl:cost-center" in DEFAULT_LEGACY_KEYS
        assert "acdl:ref" in DEFAULT_LEGACY_KEYS

    def test_duplicates_not_duplicated_in_output(self):
        # List comprehension preserves duplicates in input; the API dedups via set
        # but the function is a faithful list filter. Duplicates are unusual but
        # the function does not dedup (the UntagResources API tolerates the same
        # key once; real GetResources never returns duplicate keys).
        keys = ["acdl:owner", "acdl:owner"]
        assert acdl_keys_in(keys) == ["acdl:owner", "acdl:owner"]


class TestKeysToUntag:
    def test_empty_tags(self):
        assert keys_to_untag({"ResourceARN": "arn:...", "Tags": []}) == []

    def test_no_tags_key(self):
        assert keys_to_untag({"ResourceARN": "arn:..."}) == []

    def test_with_acdl_keys(self):
        resource = {
            "ResourceARN": "arn:aws:s3:::my-bucket",
            "Tags": [
                {"Key": "acdl:owner", "Value": "acdl"},
                {"Key": "nova:owner", "Value": "acdl"},
                {"Key": "acdl:cost-center", "Value": "acdl-default"},
                {"Key": "Name", "Value": "my-bucket"},
            ],
        }
        assert keys_to_untag(resource) == ["acdl:owner", "acdl:cost-center"]

    def test_with_only_nova_keys(self):
        resource = {
            "ResourceARN": "arn:aws:s3:::my-bucket",
            "Tags": [
                {"Key": "nova:owner", "Value": "acdl"},
                {"Key": "nova:contract", "Value": "platform"},
                {"Key": "Name", "Value": "my-bucket"},
            ],
        }
        assert keys_to_untag(resource) == []

    def test_all_5_acdl_keys(self):
        resource = {
            "ResourceARN": "arn:aws:ecs:us-east-1:123:cluster/x",
            "Tags": [
                {"Key": "acdl:owner", "Value": "v"},
                {"Key": "acdl:contract", "Value": "v"},
                {"Key": "acdl:environment", "Value": "v"},
                {"Key": "acdl:cost-center", "Value": "v"},
                {"Key": "acdl:ref", "Value": "v"},
            ],
        }
        result = keys_to_untag(resource)
        assert result == ["acdl:owner", "acdl:contract", "acdl:environment", "acdl:cost-center", "acdl:ref"]

    def test_custom_legacy_keys(self):
        resource = {
            "ResourceARN": "arn:...",
            "Tags": [
                {"Key": "acdl:owner", "Value": "v"},
                {"Key": "acdl:contract", "Value": "v"},
            ],
        }
        # Only targeting acdl:owner
        assert keys_to_untag(resource, legacy_keys=("acdl:owner",)) == ["acdl:owner"]

    def test_malformed_tag_entry_skipped(self):
        # A tag entry without a Key is skipped gracefully
        resource = {
            "ResourceARN": "arn:...",
            "Tags": [
                {"Value": "no-key"},
                {"Key": "acdl:owner", "Value": "v"},
                "not-a-dict",
            ],
        }
        assert keys_to_untag(resource) == ["acdl:owner"]


class TestRunDryRunNoClient:
    def test_dry_run_returns_empty_summary_without_client(self):
        from untag_acdl_keys import run
        summary = run(apply=False, client=None)
        assert summary["listed"] == 0
        assert summary["untagged"] == 0
        assert summary["keys_removed"] == 0
        assert summary["errors"] == 0

    def test_dry_run_apply_false_no_mutation(self):
        # apply=False with a client still only lists (no untag)
        from untag_acdl_keys import run

        class FakeClient:
            def get_paginator(self, name):
                class P:
                    def paginate(self, **kw):
                        return iter([{"ResourceMappingList": []}])
                return P()

        summary = run(apply=False, client=FakeClient())
        assert summary["listed"] == 0
        assert summary["untagged"] == 0