from pathlib import Path

from colorama import Fore

from common import (
    cd_path,
    exit_message,
    get_env_variable_required,
    print_message,
    repository_is_flex,
)
from common.file_helpers import get_java_version, load_sdl_properties
from common.sonar_helper import SonarHelper, SonarScannerType
from src.interface.maven_project_with_docker import MavenProjectWithDockerInterface


class MavenSDL(MavenProjectWithDockerInterface):
    def __init__(self) -> None:
        super().__init__()
        self.properties = load_sdl_properties()

        if not self.properties:
            exit_message(
                "O projeto está usando o script de SDL porém não possui "
                "nenhuma propriedade no/não possui o arquivo sdl.properties."
            )

        self.generator_java_output = self._get_java_output()
        self.output_pom_exists = Path(f"{self.generator_java_output}/pom.xml").is_file()
        self.sources_generated = False

    def set_version(self):
        # Prints the sed command to update the version in the `sdl.properties` file for logging purposes,
        # allowing the user to execute it on their local machine.
        print_message(
            f'sed -i "s/generator.app.version=.*/generator.app.version={self.version}/" sdl.properties',
            Fore.LIGHTGREEN_EX,
        )
        self._replace_line_in_file(
            "sdl.properties",
            "generator.app.version=",
            f"generator.app.version={self.version}",
        )

        super().set_version()

        if self.output_pom_exists or self._custom_parent_file():
            self._execute_mvn_command(
                f"versions:set -DgenerateBackupPoms=false -DnewVersion={self.version} "
                f"-DprocessAllModules -N versions:update-child-modules --file {self.generator_java_output}"
            )
        else:
            self._run_generate_sources()

    def generate(self):
        super().generate()

        if self.output_pom_exists:
            self._run_generate_sources()

    def compile(self):
        if self.buildable_project.skip_build():
            return

        self._execute_mvn_command(
            f"install -DskipTests=true -Ddockerfile.skip=true --file {self.generator_java_output}"
        )

    def unit_test(self):
        if self.buildable_project.skip_build():
            return

        self._docker_login()

        self._execute_mvn_command(
            f"install -Ddockerfile.skip=true --file {self.generator_java_output}"
        )

    def sonar_scanner(self):
        sonar_helper = SonarHelper(
            sonar_scanner_type=SonarScannerType.SDL,
            skip_build=self.buildable_project.skip_build(),
        )
        sonar_helper.scanner_analyze()

    def package(self):
        java_version = get_java_version()
        if java_version >= "17":
            project_root = Path(get_env_variable_required("CI_PROJECT_DIR"))

            self._execute_mvn_command(
                f"deploy -DskipTests=true -Ddockerfile.skip=true --file {self.generator_java_output}"
            )

            cd_path(f"{self.generator_java_output}/impl/target/docker")
            self._push_image()

            if repository_is_flex():
                cd_path(str(project_root))
                cd_path(f"{self.generator_java_output}/http-impl/target/docker")

                self.image_name = f"{self.image_name}-http"
                self._push_image()
        else:
            self._docker_login()
            self._create_repository()
            self._execute_mvn_command(
                f"deploy -DskipTests=true --file {self.generator_java_output}"
            )

    def build_docker_image(self):
        self._docker_login()
        java_version = get_java_version()
        if java_version >= "17":
            project_root = Path(get_env_variable_required("CI_PROJECT_DIR"))
            cd_path(f"{self.generator_java_output}/impl/target/docker")
            self._build_image()
            self._save_image()

            if repository_is_flex():
                cd_path(str(project_root))
                cd_path(f"{self.generator_java_output}/http-impl/target/docker")

                self.image_name = f"{self.image_name}-http"
                self._build_image()
                self._save_image()
        else:
            self._execute_mvn_command(
                f"install -DskipTests=true --file {self.generator_java_output}"
            )
            self._save_image()

    def trivy_scan_image(self, custom_args=""):
        for tar_file in (
            Path(self.ci_project_dir)
            .joinpath(self.ci_project_dir, "docker_image")
            .glob("*.tar")
        ):
            self.image_name = tar_file.stem
            super().trivy_scan_image(custom_args="--skip-dirs app")

    def _get_java_output(self) -> str:
        try:
            output = self.properties["generator.java.output"]
        except KeyError:
            output = get_env_variable_required("GENERATOR_JAVA_OUTPUT")

        return output

    @staticmethod
    def _replace_line_in_file(file_path, line_to_find, new_line):
        file_path = Path(file_path)

        if not file_path.is_file():
            exit_message(f"File {file_path} not found")

        # Open the file in read mode and read lines
        with open(file_path, "r", encoding="utf-8") as file:
            lines = file.readlines()

        # Replace the line
        for i, line in enumerate(lines):
            if line.startswith(line_to_find):
                lines[i] = new_line + "\n"
                break

        # Open the file in write mode and write the modified lines
        with open(file_path, "w", encoding="utf-8") as file:
            file.writelines(lines)

    def _run_generate_sources(self):
        if not self.sources_generated:
            self._execute_mvn_command("generate-sources")
            self.sources_generated = True

    def _custom_parent_file(self):
        if "generator.java.parent.pom.custom" in self.properties:
            self._run_generate_sources()
            return True
        return False

    def _check_mutations_xml(self, xml_dir="target/pit-reports/"):
        return super()._check_mutations_xml("java/impl/target/pit-reports/")
