# pylint: disable=E1101

# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os.path
import re

from docker.errors import NotFound

import pytest
import yaml


@pytest.fixture(scope="class")
def container_run_default(request, docker_client, gerrit_init_image, tmp_path_factory):
    tmp_site_dir = tmp_path_factory.mktemp("gerrit_site")
    container_run = docker_client.containers.run(
        image=gerrit_init_image.id,
        user="gerrit",
        volumes={tmp_site_dir: {"bind": "/var/gerrit", "mode": "rw"}},
        detach=True,
        auto_remove=True,
    )

    def stop_container():
        try:
            container_run.stop(timeout=1)
        except NotFound:
            print("Container already stopped.")

    request.addfinalizer(stop_container)

    return container_run


@pytest.fixture(scope="class")
def init_config_dir(tmp_path_factory):
    return tmp_path_factory.mktemp("init_config")


@pytest.fixture(scope="class")
def tmp_site_dir(tmp_path_factory):
    return tmp_path_factory.mktemp("gerrit_site")


@pytest.fixture(scope="class")
def container_run_endless(
    docker_client, gerrit_init_image, init_config_dir, tmp_site_dir
):
    container_run = docker_client.containers.run(
        image=gerrit_init_image.id,
        entrypoint="/bin/ash",
        command=["-c", "tail -f /dev/null"],
        user="gerrit",
        volumes={
            tmp_site_dir: {"bind": "/var/gerrit", "mode": "rw"},
            init_config_dir: {"bind": "/var/config", "mode": "rw"},
        },
        detach=True,
        auto_remove=True,
    )

    yield container_run
    container_run.stop(timeout=1)


@pytest.mark.docker
@pytest.mark.incremental
@pytest.mark.integration
class TestGerritInitEmptySite:
    @pytest.mark.timeout(60)
    def test_gerrit_init_gerrit_is_initialized(self, container_run_default):
        def wait_for_init_success_message():
            log = container_run_default.logs().decode("utf-8")
            return log, re.search(r"Initialized /var/gerrit", log)

        while not wait_for_init_success_message():
            continue

    @pytest.mark.timeout(60)
    def test_gerrit_init_exits_after_init(self, container_run_default):
        assert container_run_default.wait()["StatusCode"] == 0


@pytest.fixture(
    scope="function",
    params=[
        ["replication", "reviewnotes"],
        ["replication", "reviewnotes", "hooks"],
        ["download-commands"],
        [],
    ],
)
def plugins_to_install(request):
    return request.param


@pytest.mark.docker
@pytest.mark.incremental
@pytest.mark.integration
class TestGerritInitPluginInstallation:
    def _configure_packaged_plugins(self, file_path, plugins):
        with open(file_path, "w", encoding="utf-8") as f:
            yaml.dump({"packagedPlugins": plugins}, f, default_flow_style=False)

    def test_gerrit_init_plugins_are_installed(
        self,
        container_run_endless,
        init_config_dir,
        plugins_to_install,
        tmp_site_dir,
        required_plugins,
    ):
        self._configure_packaged_plugins(
            os.path.join(init_config_dir, "init.yaml"), plugins_to_install
        )

        exit_code, _ = container_run_endless.exec_run(
            "python3 /var/tools/gerrit-initializer -s /var/gerrit -c /var/config/init.yaml init"
        )
        assert exit_code == 0

        plugins_path = os.path.join(tmp_site_dir, "plugins")

        for plugin in plugins_to_install:
            assert os.path.exists(os.path.join(plugins_path, f"{plugin}.jar"))

        installed_plugins = os.listdir(plugins_path)
        expected_plugins = plugins_to_install + required_plugins
        for plugin in installed_plugins:
            assert os.path.splitext(plugin)[0] in expected_plugins

    def test_required_plugins_are_installed(
        self, container_run_endless, init_config_dir, tmp_site_dir, required_plugins
    ):
        self._configure_packaged_plugins(
            os.path.join(init_config_dir, "init.yaml"), ["hooks"]
        )

        exit_code, _ = container_run_endless.exec_run(
            "python3 /var/tools/gerrit-initializer -s /var/gerrit -c /var/config/init.yaml init"
        )
        assert exit_code == 0

        for plugin in required_plugins:
            assert os.path.exists(
                os.path.join(tmp_site_dir, "plugins", f"{plugin}.jar")
            )

    def test_libraries_are_symlinked(
        self, container_run_endless, init_config_dir, tmp_site_dir
    ):
        with open(
            os.path.join(init_config_dir, "init.yaml"), "w", encoding="utf-8"
        ) as f:
            yaml.dump(
                {"packagedPlugins": ["hooks"], "installAsLibrary": ["hooks"]},
                f,
                default_flow_style=False,
            )

        exit_code, _ = container_run_endless.exec_run(
            "python3 /var/tools/gerrit-initializer -s /var/gerrit -c /var/config/init.yaml init"
        )
        assert exit_code == 0

        assert os.path.exists(os.path.join(tmp_site_dir, "plugins", "hooks.jar"))
        assert os.path.islink(os.path.join(tmp_site_dir, "lib", "hooks.jar"))

        exit_code, output = container_run_endless.exec_run(
            "readlink -f /var/gerrit/lib/hooks.jar"
        )
        assert exit_code == 0
        assert output.decode("utf-8").strip() == "/var/gerrit/plugins/hooks.jar"

    def test_library_symlink_fails_without_plugin(
        self, container_run_endless, init_config_dir
    ):
        with open(
            os.path.join(init_config_dir, "init.yaml"), "w", encoding="utf-8"
        ) as f:
            yaml.dump(
                {"packagedPlugins": ["hooks"], "installAsLibrary": ["saml"]},
                f,
                default_flow_style=False,
            )

        exit_code, output = container_run_endless.exec_run(
            "python3 /var/tools/gerrit-initializer -s /var/gerrit -c /var/config/init.yaml init"
        )
        assert exit_code == 1
        assert (
            output.decode("utf-8")
            .strip()
            .endswith(
                "FileNotFoundError: Could not find plugin saml to symlink to lib-directory."
            )
        )
