# Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
# OpenOLC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         `http://license.coscl.org.cn/MulanPSL2`
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.

import unittest

from olc.bean.olc_control_request import OlcControlRequest
from olc.bean.tag_group import OlcTag
from olc.control.matcher.operation.operation_matcher import (
    EqualMatcher,
    DefaultMatcher,
    OperationMatcherFactory,
    OperationMatcher,
)


class TestEqualMatcher(unittest.TestCase):

    def test_match_tag_exists_value_equals(self):
        request = OlcControlRequest(tags={"env": "prod"})
        olc_tag = OlcTag(match="equal", tag="env", value="prod")
        self.assertTrue(EqualMatcher.match(request, olc_tag))

    def test_match_tag_exists_value_not_equals(self):
        request = OlcControlRequest(tags={"env": "prod"})
        olc_tag = OlcTag(match="equal", tag="env", value="staging")
        self.assertFalse(EqualMatcher.match(request, olc_tag))

    def test_match_tag_not_in_request(self):
        request = OlcControlRequest(tags={"region": "us"})
        olc_tag = OlcTag(match="equal", tag="env", value="prod")
        self.assertFalse(EqualMatcher.match(request, olc_tag))

    def test_match_empty_tags_in_request(self):
        request = OlcControlRequest(tags={})
        olc_tag = OlcTag(match="equal", tag="env", value="prod")
        self.assertFalse(EqualMatcher.match(request, olc_tag))

    def test_match_none_value_in_tag(self):
        request = OlcControlRequest(tags={"env": "prod"})
        olc_tag = OlcTag(match="equal", tag="env", value=None)
        self.assertFalse(EqualMatcher.match(request, olc_tag))

    def test_match_none_value_in_request(self):
        request = OlcControlRequest(tags={"env": None})
        olc_tag = OlcTag(match="equal", tag="env", value="prod")
        self.assertFalse(EqualMatcher.match(request, olc_tag))

    def test_match_both_none_values(self):
        request = OlcControlRequest(tags={"env": None})
        olc_tag = OlcTag(match="equal", tag="env", value=None)
        self.assertFalse(EqualMatcher.match(request, olc_tag))

    def test_match_empty_string_value(self):
        request = OlcControlRequest(tags={"env": ""})
        olc_tag = OlcTag(match="equal", tag="env", value="")
        self.assertTrue(EqualMatcher.match(request, olc_tag))

    def test_match_case_sensitive(self):
        request = OlcControlRequest(tags={"env": "Prod"})
        olc_tag = OlcTag(match="equal", tag="env", value="prod")
        self.assertFalse(EqualMatcher.match(request, olc_tag))

    def test_match_multiple_tags_in_request(self):
        request = OlcControlRequest(tags={"env": "prod", "region": "us", "app": "web"})
        olc_tag = OlcTag(match="equal", tag="region", value="us")
        self.assertTrue(EqualMatcher.match(request, olc_tag))


class TestDefaultMatcher(unittest.TestCase):

    def test_match_tag_exists_value_not_empty(self):
        request = OlcControlRequest(tags={"env": "prod"})
        olc_tag = OlcTag(match="default", tag="env", value="any_value")
        self.assertTrue(DefaultMatcher.match(request, olc_tag))

    def test_match_tag_not_in_request(self):
        request = OlcControlRequest(tags={"region": "us"})
        olc_tag = OlcTag(match="default", tag="env", value="any_value")
        self.assertFalse(DefaultMatcher.match(request, olc_tag))

    def test_match_empty_tags_in_request(self):
        request = OlcControlRequest(tags={})
        olc_tag = OlcTag(match="default", tag="env", value="any_value")
        self.assertFalse(DefaultMatcher.match(request, olc_tag))

class TestOperationMatcherFactory(unittest.TestCase):

    def test_get_equal_returns_callable(self):
        matcher = OperationMatcherFactory.get_operation("equal")
        self.assertIsNotNone(matcher)
        self.assertIsInstance(matcher, EqualMatcher)

    def test_get_default_returns_callable(self):
        matcher = OperationMatcherFactory.get_operation("default")
        self.assertIsNotNone(matcher)
        self.assertIsInstance(matcher, DefaultMatcher)

    def test_get_unknown_returns_none(self):
        matcher = OperationMatcherFactory.get_operation("unknown")
        self.assertIsNone(matcher)

    def test_get_empty_string_returns_none(self):
        matcher = OperationMatcherFactory.get_operation("")
        self.assertIsNone(matcher)

    def test_get_none_returns_none(self):
        matcher = OperationMatcherFactory.get_operation(None)
        self.assertIsNone(matcher)

    def test_equal_factory_creates_equal_matcher(self):
        matcher = OperationMatcherFactory.get_operation("equal")
        self.assertIsInstance(matcher, EqualMatcher)

    def test_default_factory_creates_default_matcher(self):
        matcher = OperationMatcherFactory.get_operation("default")
        self.assertIsInstance(matcher, DefaultMatcher)

    def test_equal_factory_matcher_works(self):
        matcher = OperationMatcherFactory.get_operation("equal")
        request = OlcControlRequest(tags={"env": "prod"})
        olc_tag = OlcTag(match="equal", tag="env", value="prod")
        self.assertTrue(matcher.match(request, olc_tag))

    def test_default_factory_matcher_works(self):
        matcher = OperationMatcherFactory.get_operation("default")
        request = OlcControlRequest(tags={"env": "prod"})
        olc_tag = OlcTag(match="default", tag="env", value="any")
        self.assertTrue(matcher.match(request, olc_tag))

    def test_switch_dict_has_equal_and_default(self):
        self.assertIn("equal", OperationMatcherFactory.switch)
        self.assertIn("default", OperationMatcherFactory.switch)


class TestOperationMatcherABC(unittest.TestCase):

    def test_operation_matcher_has_match_method(self):
        self.assertTrue(hasattr(OperationMatcher, 'match'))

    def test_operation_matcher_match_returns_none(self):
        result = OperationMatcher.match(OlcControlRequest(), OlcTag())
        self.assertIsNone(result)

    def test_equal_matcher_inherits_operation_matcher(self):
        self.assertTrue(issubclass(EqualMatcher, OperationMatcher))

    def test_default_matcher_inherits_operation_matcher(self):
        self.assertTrue(issubclass(DefaultMatcher, OperationMatcher))


if __name__ == '__main__':
    unittest.main()