import os
import shutil
from typing import Any, Optional
from unittest import TestCase
from unittest.mock import patch

from yaml.scanner import ScannerError

from config import Config
from tool import Tool


class TestConfig(TestCase):
    def get_dir_side_effect(self, folder: str, root: "Optional[str]" = None) -> "Optional[str]":
        if folder in ["valid_config", "dummy_config", "missing_folder"]:
            return str(Tool.formatted_from_os(os.path.join(os.path.dirname(__file__), "resources", folder)))
        # Use the original method from the class, passing a new instance or self if relevant
        # Accessing the original method requires unpatching or saving it.
        # Simpler: just return None or duplicate logic for now since we don't expect other calls.
        return None

    @patch("tool.Tool.get_dir")
    def test_get_data(self, mock_get_dir: "Any") -> None:
        mock_get_dir.side_effect = self.get_dir_side_effect
        config = Config()
        config.data.clear()
        config.get_data(_config_dir="valid_config")

        assert config.data == {
            "valid_config": {
                "key1": {"sub_key": "value", "sub_key2": "value", "sub_key3": "value", "sub_key4": "value"}
            }
        }

    @patch("tool.Tool.get_dir")
    def test_get_data_dummy_data(self, mock_get_dir: "Any") -> None:
        mock_get_dir.side_effect = self.get_dir_side_effect
        config = Config()
        config.data.clear()
        try:
            config.get_data(_config_dir="dummy_config")
            self.fail("ScannerError expected here!")
        except ScannerError:
            assert config.data == {}

    @patch("tool.Tool.get_dir")
    def test_get_data_dummy_folder(self, mock_get_dir: "Any") -> None:
        mock_get_dir.side_effect = self.get_dir_side_effect
        config = Config()
        config.data.clear()
        config.get_data(_config_dir="missing_folder", create_if_not_exist=True)
        assert os.path.exists("missing_folder")
        shutil.rmtree("missing_folder")

    @patch("tool.Tool.get_dir")
    def test_get_data_from_specific_file(self, mock_get_dir: "Any") -> None:
        mock_get_dir.side_effect = self.get_dir_side_effect
        config = Config()
        config.data.clear()
        config.get_data(_config_dir="valid_config", needed_file="valid_config.yml")

        assert config.data == {
            "valid_config": {
                "key1": {"sub_key": "value", "sub_key2": "value", "sub_key3": "value", "sub_key4": "value"}
            }
        }
