from __future__ import annotations

import os
import shutil

import pytest

from pre_commit_hooks.check_merge_conflict import main
from pre_commit_hooks.util import cmd_output
from testing.util import get_resource_path
from testing.util import git_commit


@pytest.fixture
def f1_is_a_conflict_file(tmpdir):
    # Make a merge conflict
    repo1 = tmpdir.join('repo1')
    repo1_f1 = repo1.join('f1')
    repo2 = tmpdir.join('repo2')
    repo2_f1 = repo2.join('f1')

    cmd_output('git', 'init', '--', str(repo1))
    with repo1.as_cwd():
        repo1_f1.ensure()
        cmd_output('git', 'add', '.')
        git_commit('-m', 'commit1')

    cmd_output('git', 'clone', str(repo1), str(repo2))

    # Commit in mainline
    with repo1.as_cwd():
        repo1_f1.write('parent\n')
        git_commit('-am', 'mainline commit2')

    # Commit in clone and pull
    with repo2.as_cwd():
        repo2_f1.write('child\n')
        git_commit('-am', 'clone commit2')
        cmd_output('git', 'pull', '--no-rebase', retcode=None)
        # We should end up in a merge conflict!
        f1 = repo2_f1.read()
        assert f1.startswith(
            '<<<<<<< HEAD\n'
            'child\n'
            '=======\n'
            'parent\n'
            '>>>>>>>',
        ) or f1.startswith(
            '<<<<<<< HEAD\n'
            'child\n'
            # diff3 conflict style git merges add this line:
            '||||||| merged common ancestors\n'
            '=======\n'
            'parent\n'
            '>>>>>>>',
        ) or f1.startswith(
            # .gitconfig with [pull] rebase = preserve causes a rebase which
            # flips parent / child
            '<<<<<<< HEAD\n'
            'parent\n'
            '=======\n'
            'child\n'
            '>>>>>>>',
        )
        assert os.path.exists(os.path.join('.git', 'MERGE_MSG'))
        yield repo2


@pytest.fixture
def repository_pending_merge(tmpdir):
    # Make a (non-conflicting) merge
    repo1 = tmpdir.join('repo1')
    repo1_f1 = repo1.join('f1')
    repo2 = tmpdir.join('repo2')
    repo2_f1 = repo2.join('f1')
    repo2_f2 = repo2.join('f2')
    cmd_output('git', 'init', str(repo1))
    with repo1.as_cwd():
        repo1_f1.ensure()
        cmd_output('git', 'add', '.')
        git_commit('-m', 'commit1')

    cmd_output('git', 'clone', str(repo1), str(repo2))

    # Commit in mainline
    with repo1.as_cwd():
        repo1_f1.write('parent\n')
        git_commit('-am', 'mainline commit2')

    # Commit in clone and pull without committing
    with repo2.as_cwd():
        repo2_f2.write('child\n')
        cmd_output('git', 'add', '.')
        git_commit('-m', 'clone commit2')
        cmd_output('git', 'pull', '--no-commit', '--no-rebase')
        # We should end up in a pending merge
        assert repo2_f1.read() == 'parent\n'
        assert repo2_f2.read() == 'child\n'
        assert os.path.exists(os.path.join('.git', 'MERGE_HEAD'))
        yield repo2


@pytest.mark.usefixtures('f1_is_a_conflict_file')
def test_merge_conflicts_git(capsys):
    assert main(['f1']) == 1
    out, _ = capsys.readouterr()
    assert out == (
        "f1:1: Merge conflict string '<<<<<<<' found\n"
        "f1:3: Merge conflict string '=======' found\n"
        "f1:5: Merge conflict string '>>>>>>>' found\n"
    )


@pytest.mark.parametrize(
    'contents', (b'<<<<<<< HEAD\n', b'=======\n', b'>>>>>>> main\n'),
)
def test_merge_conflicts_failing(contents, repository_pending_merge):
    repository_pending_merge.join('f2').write_binary(contents)
    assert main(['f2']) == 1


@pytest.mark.parametrize(
    'contents', (b'# <<<<<<< HEAD\n', b'# =======\n', b'import mod', b''),
)
def test_merge_conflicts_ok(contents, f1_is_a_conflict_file):
    f1_is_a_conflict_file.join('f1').write_binary(contents)
    assert main(['f1']) == 0


@pytest.mark.usefixtures('f1_is_a_conflict_file')
def test_ignores_binary_files():
    shutil.copy(get_resource_path('img1.jpg'), 'f1')
    assert main(['f1']) == 0


def test_does_not_care_when_not_in_a_merge(tmpdir):
    f = tmpdir.join('README.md')
    f.write_binary(b'problem\n=======\n')
    assert main([str(f.realpath())]) == 0


def test_care_when_assumed_merge(tmpdir):
    f = tmpdir.join('README.md')
    f.write_binary(b'problem\n=======\n')
    assert main([str(f.realpath()), '--assume-in-merge']) == 1


def test_worktree_merge_conflicts(f1_is_a_conflict_file, tmpdir, capsys):
    worktree = tmpdir.join('worktree')
    cmd_output('git', 'worktree', 'add', str(worktree))
    with worktree.as_cwd():
        cmd_output(
            'git', 'pull', '--no-rebase', 'origin', 'HEAD', retcode=None,
        )
        msg = f1_is_a_conflict_file.join('.git/worktrees/worktree/MERGE_MSG')
        assert msg.exists()
        test_merge_conflicts_git(capsys)
