#!/usr/bin/python3
"""Tests for package process"""

import os
import sys
# noinspection PyPep8Naming
import xml.etree.ElementTree as ET
from configparser import ConfigParser

# noinspection PyUnresolvedReferences
from pytest_mock import mocker

os.chdir(os.path.dirname(__file__))
sys.path.append('../src')

# noinspection PyUnresolvedReferences
from maven_check_versions.process import (  # noqa: E402
    process_rest, process_repository, process_repositories,
    process_modules_if_required, process_artifact,
    process_dependencies, process_pom, process_main
)

# noinspection PyUnresolvedReferences
from maven_check_versions.logutils import (  # noqa: E402
    configure_logging, log_skip_if_required,
    log_search_if_required, log_invalid_if_required
)

# noinspection PyUnresolvedReferences
from maven_check_versions.config import (  # noqa: E402
    get_config_value, config_items
)

# noinspection PyUnresolvedReferences
from maven_check_versions.utils import (  # noqa: E402
    get_dependency_identifiers, collect_dependencies,
    resolve_version, get_version,
)

ns_mappings = {'xmlns': 'http://maven.apache.org/POM/4.0.0'}  # NOSONAR


# noinspection PyShadowingNames
def test_process_main(mocker, monkeypatch):
    monkeypatch.setenv('HOME', os.path.dirname(__file__))
    mock_exists = mocker.patch('os.path.exists')
    mock_exists.side_effect = [False, False, False, True]
    mocker.patch('builtins.open', mocker.mock_open(read_data="[base]\ncache_off = false"))
    mocker.patch('maven_check_versions.cache.load_cache', return_value={})
    mocker.patch('maven_check_versions.process.process_pom')
    mocker.patch('maven_check_versions.cache.save_cache')
    process_main({'pom_file': 'pom.xml'})

    mock_exists.side_effect = [False, False, False, True]
    mocker.patch('maven_check_versions.process.process_artifact')
    process_main({'find_artifact': 'pom.xml'})

    mock_exists.side_effect = [False, False, False, True]
    mock_config_items = mocker.patch('maven_check_versions.config.config_items')
    mock_config_items.return_value = [('key', 'pom.xml')]
    process_main({})


# noinspection PyShadowingNames
def test_process_rest(mocker):
    _service_rest = lambda: process_rest(
        {}, mocker.Mock(), {}, 'group', 'artifact', '1.0', 'section',
        'repository', 'http://example.com/pom.pom', (), True  # NOSONAR
    )

    mock_check_versions = mocker.patch('maven_check_versions.utils.check_versions')
    mock_check_versions.return_value = True
    mock_requests = mocker.patch('requests.get')
    mock_requests.return_value = mocker.Mock(status_code=200, text="""
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
        <version>1.0</version>
        <version>1.1</version>
    </root>
    """.lstrip())
    assert _service_rest()

    text = '<html><body><table><a>1.0</a><a>1.1</a></table></body></html>'
    mock_response = mocker.Mock(status_code=200, text=text)
    mock_requests.side_effect = [mocker.Mock(status_code=404), mock_response]
    assert _service_rest()

    mock_response = mocker.Mock(status_code=404)
    mock_requests.side_effect = [mock_response, mock_response]
    assert not _service_rest()


# noinspection PyShadowingNames
def test_process_repository(mocker):
    config_parser = ConfigParser()
    config_parser.optionxform = str
    config_parser.read_string("""
    [section]
    base = https://repo1.maven.org
    path = maven2
    repo = maven-central
    service_rest = true
    auth = true
    """)
    args = {'user': 'user', 'password': 'pass'}  # NOSONAR
    _process_repository = lambda: process_repository(
        {}, config_parser, args, 'group', 'artifact', '1.0',
        'repository', 'section', True
    )

    mock_requests = mocker.patch('requests.get')
    mock_requests.return_value = mocker.Mock(status_code=200, text="""
    <?xml version="1.0" encoding="UTF-8"?>
    <metadata>
        <versioning>
            <versions>
                <version>1.0</version>
                <version>1.1</version>
            </versions>
        </versioning>
    </metadata>
    """.lstrip())
    mock_check_versions = mocker.patch('maven_check_versions.utils.check_versions')
    mock_check_versions.return_value = True
    assert _process_repository()

    mock_requests.return_value = mocker.Mock(status_code=404)
    mock_process_rest = mocker.patch('maven_check_versions.process.process_rest')
    mock_process_rest.return_value = True
    assert _process_repository()

    config_parser.set('section', 'service_rest', 'false')
    assert not _process_repository()


# noinspection PyShadowingNames
def test_process_repositories(mocker):
    config_parser = ConfigParser()
    config_parser.optionxform = str
    config_parser.read_string("""
    [repositories]
        repo1 = maven-central
        repo2 = custom-repo
    [maven-central]
        base = https://repo1.maven.org
        path = maven2
    [custom-repo]
        base = https://custom.repo
        path = maven2
    """)
    mock_process_repository = mocker.patch('maven_check_versions.process.process_repository')
    mock_process_repository.return_value = True
    assert process_repositories('artifact', {}, config_parser, 'group', {}, True, '1.0')

    config_parser.remove_section('repositories')
    config_parser.read_string("[repositories]")
    assert not process_repositories('artifact', {}, config_parser, 'group', {}, True, '1.0')


# noinspection PyShadowingNames
def test_process_modules_if_required(mocker):
    config_parser = ConfigParser()
    config_parser.optionxform = str
    config_parser.read_string("[base]\nprocess_modules = true")
    root = ET.fromstring("""
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0">
        <modules>
            <module>module1</module>
            <module>module2</module>
        </modules>
    </project>
    """.lstrip())
    mocker.patch('os.path.exists', return_value=True)
    mock_process_pom = mocker.patch('maven_check_versions.process.process_pom')
    process_modules_if_required({}, config_parser, {}, root, 'pom.xml', ns_mappings)
    assert mock_process_pom.call_count == 2


# noinspection PyShadowingNames
def test_process_artifact(mocker):
    config_parser = ConfigParser()
    config_parser.optionxform = str
    config_parser.read_string("""
    [base]
        show_search = true
    [repositories]
        repo1 = maven-central
        repo2 = custom-repo
    [maven-central]
        base = https://repo1.maven.org
        path = maven2
    [custom-repo]
        base = https://custom.repo
        path = maven2
    """)
    mock_logging = mocker.patch('logging.info')
    mock_process_repository = mocker.patch('maven_check_versions.process.process_repository')
    mock_process_repository.return_value = True
    process_artifact(None, config_parser, {}, 'group:artifact:1.0')
    mock_logging.assert_called_once_with('Search: group:artifact:1.0')
    mock_process_repository.assert_called_once()

    mock_logging = mocker.patch('logging.warning')
    mock_process_repository.return_value = False
    process_artifact(None, config_parser, {}, 'group:artifact:1.0')
    mock_logging.assert_called_once_with('Not Found: group:artifact, current:1.0')


# noinspection PyShadowingNames
def test_process_dependencies(mocker):
    config_parser = ConfigParser()
    config_parser.optionxform = str
    config_parser.read_string("[base]\nempty_version = true\nshow_skip = true")
    root = ET.fromstring("""
        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0">
            <dependencies>
                <dependency xmlns="http://maven.apache.org/POM/4.0.0">
                    <artifactId>artifact</artifactId>
                    <groupId>group</groupId>
                    <version>1.0</version>
                </dependency>
            </dependencies>
        </project>
        """.lstrip())
    dependencies = collect_dependencies(root, ns_mappings, config_parser, {})
    _process_dependencies = lambda data=None: process_dependencies(
        data, config_parser, {}, dependencies, ns_mappings, root, True
    )

    mock_gdi = mocker.patch('maven_check_versions.utils.get_dependency_identifiers')
    mock_gdi.return_value = ('artifact', None)
    mock_logging = mocker.patch('logging.error')
    _process_dependencies()
    mock_logging.assert_called_once()

    mock_gdi.return_value = ('artifact', 'group')
    mock_get_version = mocker.patch('maven_check_versions.utils.get_version')
    mock_get_version.return_value = ('1.0', True)
    mock_logging = mocker.patch('logging.warning')
    _process_dependencies()
    mock_logging.assert_called_once()

    mock_get_version.return_value = ('1.0', False)
    mocker.patch('maven_check_versions.cache.process_cache', return_value=True)
    _process_dependencies({'group:artifact': ()})

    mocker.patch('maven_check_versions.process.process_repositories', return_value=False)
    mock_logging = mocker.patch('logging.warning')
    _process_dependencies()
    mock_logging.assert_called_once()


# noinspection PyShadowingNames
def test_process_pom(mocker):
    mock_get_pom_tree = mocker.patch('maven_check_versions.utils.get_pom_tree')
    mock_get_pom_tree.return_value = ET.ElementTree(ET.fromstring("""
    <project xmlns="http://maven.apache.org/POM/4.0.0">
        <artifactId>artifact</artifactId>
        <groupId>group</groupId>
        <version>1.0</version>
        <dependencies>
            <dependency>
                <artifactId>artifact</artifactId>
                <groupId>group</groupId>
                <version>1.0</version>
            </dependency>
        </dependencies>
    </project>
    """))
    mock_cd = mocker.patch('maven_check_versions.utils.collect_dependencies')
    mock_pd = mocker.patch('maven_check_versions.process.process_dependencies')
    mock_pmir = mocker.patch('maven_check_versions.process.process_modules_if_required')
    process_pom({}, mocker.Mock(), {}, 'pom.xml', 'prefix')
    mock_get_pom_tree.assert_called_once()
    mock_cd.assert_called_once()
    mock_pd.assert_called_once()
    mock_pmir.assert_called_once()
