# 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,
        platform="linux/amd64",
    )

    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,
        platform="linux/amd64",
    )

    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."
            )
        )
