from __future__ import annotations

import os
import subprocess
from unittest import mock

import pytest

from pre_commit_hooks.forbid_new_submodules import main
from testing.util import git_commit


@pytest.fixture
def git_dir_with_git_dir(tmpdir):
    with tmpdir.as_cwd():
        subprocess.check_call(('git', 'init', '.'))
        git_commit('--allow-empty', '-m', 'init')
        subprocess.check_call(('git', 'init', 'foo'))
        git_commit('--allow-empty', '-m', 'init', cwd=str(tmpdir.join('foo')))
        yield


@pytest.mark.parametrize(
    'cmd',
    (
        # Actually add the submodule
        ('git', 'submodule', 'add', './foo'),
        # Sneaky submodule add (that doesn't show up in .gitmodules)
        ('git', 'add', 'foo'),
    ),
)
def test_main_new_submodule(git_dir_with_git_dir, capsys, cmd):
    subprocess.check_call(cmd)
    assert main(('random_non-related_file',)) == 0
    assert main(('foo',)) == 1
    out, _ = capsys.readouterr()
    assert out.startswith('foo: new submodule introduced\n')


def test_main_new_submodule_committed(git_dir_with_git_dir, capsys):
    rev_parse_cmd = ('git', 'rev-parse', 'HEAD')
    from_ref = subprocess.check_output(rev_parse_cmd).decode().strip()
    subprocess.check_call(('git', 'submodule', 'add', './foo'))
    git_commit('-m', 'new submodule')
    to_ref = subprocess.check_output(rev_parse_cmd).decode().strip()
    with mock.patch.dict(
        os.environ,
        {'PRE_COMMIT_FROM_REF': from_ref, 'PRE_COMMIT_TO_REF': to_ref},
    ):
        assert main(('random_non-related_file',)) == 0
        assert main(('foo',)) == 1
    out, _ = capsys.readouterr()
    assert out.startswith('foo: new submodule introduced\n')


def test_main_no_new_submodule(git_dir_with_git_dir):
    open('test.py', 'a+').close()
    subprocess.check_call(('git', 'add', 'test.py'))
    assert main(('test.py',)) == 0
