import os
import pytest
from pathlib import Path

from oaa.run import main

# from oaa.settings_utils import SourceType
from oaa.settings import Config


requires_db = pytest.mark.skipif(
    not os.environ.get("DB_PASSWORD"),
    reason="requires DB_PASSWORD environment variable",
)


def test_this_config(config):
    assert config


def test_run_help(capsys):

    main(cli_args=["custom_app", "--help"])

    captured = capsys.readouterr()

    output_expected = [
        "oaa",
        "--help",
        "COMMAND is one of the following:",
    ]

    for output in output_expected:
        # print(captured.out)
        assert output in captured.out

    # print('-' * 20)


def test_run_with_config(capsys):

    BASE_DIR = Path(os.path.dirname(os.path.realpath(__file__)))

    main(
        cli_args=[
            "custom_app",
            "show_config",
            "--config",
            str(BASE_DIR / "tests" / "config-v2.yaml"),
        ]
    )

    captured = capsys.readouterr()

    output_expected = [
        '"log_level": "INFO"',
    ]

    for output in output_expected:
        # print(captured.out)
        assert output in captured.out


log_levelS = ["DEBUG", "INFO", "TRACE", "ERROR"]


@pytest.mark.parametrize("log_level", log_levelS)
def test_new_singleton_config(log_level, config):
    os.environ["log_level"] = log_level
    assert os.getenv("log_level") == log_level
    config.update()
    assert Config.get("log_level") == log_level
    assert config.get("log_level") == log_level


@pytest.mark.parametrize("log_level", log_levelS)
def test_new_singleton_config_2(log_level, config):
    os.environ["log_level"] = log_level
    assert os.getenv("log_level") == log_level
    config.update()
    assert Config.get("log_level") == log_level
    assert config.get("log_level") == log_level


def test_config_change(config):

    assert config._CONFIG
    # assert config.SOURCE_TYPE == 'NONE'
    # assert config.SOURCE_TYPE == SourceType.none
    # assert not config.DB_PASSWORD
    # assert not config.DB_USER


@requires_db
def test_load_from_config_file(config):
    config.update(config_file="./tests/config-v2.yaml")

    assert config.log_level == "ERROR"

    should_be = Path(os.path.dirname(__file__)) / "data/sample_mapping_query1.csv"  # noqa E501
    assert config.sources
    assert config.sources["users"].mapping_filepath == should_be


@requires_db
def test_mod_folder(config):
    """
    We can write custom functions for manipulating data as needed.

    A mod function is created by decorating a function with the @transformer
    decorator found in oaa.utils

    The decorator takes two parameters:
    :table: the stream of data
    :config: the configuration object

    The mod function must return a streaming object
    """

    config.update(config_file="./tests/config-v2.yaml")
    assert config.config_file
    assert config.MODULE_DIRECTORY
    mod_folder_should_be = Path(os.path.dirname(__file__)) / "modules"

    assert config.MODULE_DIRECTORY == mod_folder_should_be


@requires_db
def test_validate_command_with_valid_config(capsys):
    BASE_DIR = Path(os.path.dirname(os.path.realpath(__file__)))

    main(
        cli_args=[
            "custom_app",
            "validate",
            "--config",
            str(BASE_DIR / "tests" / "config-v2.yaml"),
        ]
    )

    captured = capsys.readouterr()

    assert "STEP 1" in captured.out
    assert "VALIDATION PASSED" in captured.out or "VALIDATION FAILED" in captured.out


@requires_db
def test_validate_command_with_config_file_short_flag(capsys):
    """Test that -c flag works as alias for --config-file."""
    BASE_DIR = Path(os.path.dirname(os.path.realpath(__file__)))

    main(
        cli_args=[
            "custom_app",
            "-c",
            str(BASE_DIR / "tests" / "config-v2.yaml"),
            "validate",
        ]
    )

    captured = capsys.readouterr()

    assert "STEP 1" in captured.out
    assert "VALIDATION PASSED" in captured.out or "VALIDATION FAILED" in captured.out


@requires_db
def test_validate_command_with_config_file_long_flag(capsys):
    """Test that --config-file flag works."""
    BASE_DIR = Path(os.path.dirname(os.path.realpath(__file__)))

    main(
        cli_args=[
            "custom_app",
            "--config-file",
            str(BASE_DIR / "tests" / "config-v2.yaml"),
            "validate",
        ]
    )

    captured = capsys.readouterr()

    assert "STEP 1" in captured.out
    assert "VALIDATION PASSED" in captured.out or "VALIDATION FAILED" in captured.out


@requires_db
def test_validate_with_missing_app_fails(capsys, tmp_path):
    """Test that config without required app fails validation."""
    invalid_config = tmp_path / "invalid_config.yaml"
    invalid_config.write_text("""
version: v2
runner_type: custom_app
sources: {}
""")

    main(cli_args=["custom_app", "validate", "--config", str(invalid_config)])

    captured = capsys.readouterr()

    assert "VALIDATION" in captured.out
