from unittest import TestCase

from abstra_internals.contracts_generated import AbstraLibApiEditorEnvVarsModel
from abstra_internals.repositories.project.project import (
    LocalProjectRepository,
    ScriptStage,
)
from abstra_internals.services.env_vars import EnvVarsRepository
from tests.fixtures import clear_dir, init_dir


class TestEnvVarsRepository(TestCase):
    def setUp(self):
        self.dir = init_dir()
        self.env_var_repo = EnvVarsRepository()
        self.project_repository = LocalProjectRepository()

    def tearDown(self):
        clear_dir(self.dir)

    def test_load_default_empty(self):
        self.assertEqual(self.env_var_repo.list(), [])

    def test_load(self):
        var = AbstraLibApiEditorEnvVarsModel(name="key", value="value")
        self.env_var_repo.set(name=var.name, value=var.value)
        self.assertEqual(self.env_var_repo.list(), [var])

    def test_set(self):
        var = AbstraLibApiEditorEnvVarsModel(name="key", value="value")
        self.env_var_repo.set(name=var.name, value=var.value)
        self.assertEqual(self.env_var_repo.list(), [var])

    def test_unset(self):
        var = AbstraLibApiEditorEnvVarsModel(name="key", value="value")
        self.env_var_repo.set(name=var.name, value=var.value)
        self.env_var_repo.unset(name=var.name)
        self.assertEqual(self.env_var_repo.list(), [])

    def test_check_no_file_is_valid(self):
        self.assertTrue(self.env_var_repo.check())

    def test_check_empty_file_is_valid(self):
        (self.dir / ".env").touch()
        self.assertTrue(self.env_var_repo.check())

    def test_check_multiple_lines_is_valid(self):
        (self.dir / ".env").write_text("key=value\nkey2=value2")
        self.assertTrue(self.env_var_repo.check())

    def test_check_no_value_is_valid(self):
        (self.dir / ".env").write_text("key=value\nkey2")
        self.assertTrue(self.env_var_repo.check())

    def test_check_invalid_returns_false(self):
        (self.dir / ".env").write_text("===")
        self.assertFalse(self.env_var_repo.check())

    def test_env_vars_in_code(self):
        project = self.project_repository.load()
        code_path = self.dir / "code.py"
        code_content = "\n".join(["import os", "os.getenv('FOO')", "os.environ['BAR']"])
        code_path.write_text(code_content)
        script = ScriptStage(
            file=str(code_path),
            id="script",
            is_initial=False,
            title="foo bar",
            workflow_position=(0, 0),
            workflow_transitions=[],
        )
        project.add_stage(script)
        self.project_repository.save(project)
        env_vars_in_code = self.env_var_repo.get_env_vars_in_code()
        self.assertEqual(env_vars_in_code.keys(), {"FOO", "BAR"})

    def test_env_vars_in_code_only_consider_first_arg(self):
        project = self.project_repository.load()
        code_path = self.dir / "code.py"
        code_content = "\n".join(["import os", "os.getenv('FOO', 'default')"])
        code_path.write_text(code_content)
        script = ScriptStage(
            file=str(code_path),
            id="script",
            is_initial=False,
            title="foo bar",
            workflow_position=(0, 0),
            workflow_transitions=[],
        )
        project.add_stage(script)
        self.project_repository.save(project)
        env_vars_in_code = self.env_var_repo.get_env_vars_in_code()
        self.assertEqual(env_vars_in_code.keys(), {"FOO"})
