# coverage run -m pytest -rA tests/test_cli.py --no-header --html=./reports/pytest/report.html --self-contained-html && coverage html #noqa E501

import pytest
import sys

from pathlib import Path

from wox.cli import main_cli
from wox.cli_control import cli_controller
from wox.constants import ExitCode
from wox.wox_steward import WoxSteward
from wox._version import __version__


# python -B -m pytest -rA -k "test_task_not_found_error_with_task"
def test_task_not_found_error_with_task(monkeypatch, capsys):
    """
        A task passed in ``wox --task`` not in .toml file must return TaskNotFoundError.
    """

    wox_toml_path = Path('tests/resources/config-files/nominal-run/wox.toml')

    monkeypatch.setattr(WoxSteward, 'wox_toml', wox_toml_path)
    monkeypatch.setattr(sys, 'argv', ['wox', '--task', 'pixegami', 'cowsa', 'bash'])

    with pytest.raises(SystemExit) as e:
        main_cli()

    assert e.value.code == ExitCode.CONFIG_ERROR.value

    out = capsys.readouterr().out

    assert 'TaskNotFoundError' in out

# python -B -m pytest -rA -k "test_task_not_found_error_with_exclude_task"
def test_task_not_found_error_with_exclude_task(monkeypatch, capsys):
    """
        A task passed in ``wox --task`` not in .toml file must return TaskNotFoundError.
    """

    wox_toml_path = Path('tests/resources/config-files/nominal-run/wox.toml')

    monkeypatch.setattr(WoxSteward, 'wox_toml', wox_toml_path)
    monkeypatch.setattr(sys, 'argv', ['wox', '--exclude-task', 'pixegami', 'cowsa', 'bash'])

    with pytest.raises(SystemExit) as e:
        main_cli()

    assert e.value.code == ExitCode.CONFIG_ERROR.value

    out = capsys.readouterr().out

    assert 'TaskNotFoundError' in out

# python -B -m pytest -rA -k "test_wox_task_parsing"
def test_wox_task_parsing(monkeypatch):
    """
        ``wox --task`` must be able to have as many tasks as necessary.
    """

    control_cli_options = ['pixegami', 'cowsay', 'bash']

    def patched_cli_controller(cli_options):
        patched_cli_controller.cli_options = cli_options
        return ExitCode.SUCCESS.value

    monkeypatch.setattr(sys, 'argv', ['wox', '--task', 'pixegami', 'cowsay', 'bash'])
    monkeypatch.setattr('wox.cli_control.cli_controller', patched_cli_controller)

    with pytest.raises(SystemExit) as e:
        main_cli()

    assert e.value.code == ExitCode.SUCCESS.value

    assert patched_cli_controller.cli_options['task'] == control_cli_options

# python -B -m pytest -rA -k "test_wox_verbosity"
def test_wox_verbosity(monkeypatch):
    """
        Wox verbosity must be boolean and not cumulative.
    """

    def patched_cli_controller(cli_options):
        patched_cli_controller.cli_options = cli_options
        return ExitCode.SUCCESS.value

    monkeypatch.setattr(sys,
        'argv', ['wox', '--verbose', '--task', 'pixegami', 'cowsay', 'bash']
    )
    monkeypatch.setattr('wox.cli_control.cli_controller', patched_cli_controller)

    with pytest.raises(SystemExit) as e:
        main_cli()

    assert e.value.code == ExitCode.SUCCESS.value

    assert isinstance(patched_cli_controller.cli_options['verbose'], bool)
    assert patched_cli_controller.cli_options['verbose'] is True

# python -B -m pytest -rA -k "test_wox_version"
@pytest.mark.parametrize('option', ['-V', '--version'])
def test_wox_version(monkeypatch, capsys, option):
    """
        ``wox --version`` (or -V) must return the version of wox.
    """

    monkeypatch.setattr(sys, 'argv', ['wox', option])

    with pytest.raises(SystemExit) as e:
        main_cli()

    assert e.value.code == ExitCode.SUCCESS.value

    out = capsys.readouterr().out

    assert __version__ in out

# python -B -m pytest -rA -k "test_wox_command_without_config_file"
def test_wox_without_config_file(monkeypatch, tmp_path, cwd_tmp_path, patched_wox_command):
    """
        Wox command run without configuration file must delete .wox directory.
    """

    tmp_dot_wox = tmp_path / '.wox'
    tmp_dot_wox.mkdir()

    monkeypatch.setattr('wox.cli_control.DOT_WOX', tmp_dot_wox)

    with pytest.raises(SystemExit):
        main_cli()

    assert not tmp_dot_wox.exists()

# python -B -m pytest -rA -k "test_wox_purge"
def test_wox_purge(monkeypatch, tmp_path):
    """
        ``wox --purge`` must delete all directories and files excepting .logs directory.
        At the end of the purge, .wox must have .logs directory, .gitignore file
        and CACHEDIR.TAG file.
    """

    dot_wox = tmp_path / '.wox'

    directory = dot_wox / '.venv'
    directory.mkdir(parents = True)

    file = dot_wox / 'file.txt'
    file.touch()

    logs_dir = dot_wox / '.logs'
    logs_dir.mkdir(parents = True)

    # Keeps the inode (file or directory identifier)
    original_logs_inode = logs_dir.stat().st_ino

    monkeypatch.setattr('wox.wox_steward.DOT_WOX', dot_wox)

    exit_code = cli_controller({'purge': True})

    assert exit_code == ExitCode.SUCCESS.value

    # Ensures that the .logs directory is exactly the same one (same inode),
    # not deleted and recreated during the purge.
    assert logs_dir.stat().st_ino == original_logs_inode

    remaining = sorted(path.name for path in (tmp_path / '.wox').iterdir())

    assert remaining == ['.gitignore', '.logs', 'CACHEDIR.TAG']
