package com.onsemi.middleware.camel.context;

import com.onsemi.middleware.ue.execeng.annotation.spring.OnCrypted;
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.models.Project;
import org.gitlab4j.api.models.RepositoryFile;
import org.gitlab4j.api.models.TreeItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import java.io.FileOutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class GitLabKaravanSourceLoader {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Value("${config.UERuntimeEngine.gitlab.karavanHubRepository.tokej}")
    @OnCrypted
    private static final String GITLAB_TOKEN;

    @Value("${config.UERuntimeEngine.gitlab.karavanHubRepository.url}")
    private static final String GITLAB_REPO_URL;

    private static final String DEFAULT_BRANCH = "main";
    private static final String GITLAB_URL = "https://gitlab.com";

    public GitLabKaravanSourceLoader() {
    }

    public void loadFolder(String interfaceName, String targetPath) {
        try {
            String folderName = interfaceName.toLowerCase();
            String projectPath = extractProjectPath(GITLAB_REPO_URL);
            GitLabApi gitLabApi = initGitLabApi();


            List<TreeItem> files = getTreeItemsSafely(gitLabApi, projectPath, folderName);
            if (files.isEmpty()) {
                log.warn("No files found in folder in GitLab repo '{}'/'{}'", projectPath, folderName);
                return;
            }

            Path outputDir = Path.of(targetPath, folderName);
            Files.createDirectories(outputDir);

            downloadAndSaveFiles(gitLabApi, projectPath, files, outputDir);

        } catch (Exception e) {
            log.error("GitLab folder loading failed", e);
        }
    }

    public GitLabApi initGitLabApi() {
        return new GitLabApi(GITLAB_URL, GITLAB_TOKEN);
    }

    private Project resolveProject(GitLabApi api, String projectPath) throws GitLabApiException {
        return api.getProjectApi().getProject(projectPath);
    }

    private List<TreeItem> getTreeItemsSafely(GitLabApi api, String projectPath, String folder) {
        try {
            return api.getRepositoryApi().getTree(projectPath, folder, DEFAULT_BRANCH, false);
        } catch (GitLabApiException e) {
            if (e.getHttpStatus() == 404) {
                log.warn("Folder '{}' not found in GitLab repo '{}'. Continuing without error.", folder, projectPath);
                return List.of(); // empty
            } else {
                throw new RuntimeException("Failed to get tree items", e);
            }
        }
    }

    private void downloadAndSaveFiles(GitLabApi api, String projectPath, List<TreeItem> files, Path outputDir) {
        for (TreeItem file : files) {
            if (!"blob".equals(file.getType().toString())) continue;

            try {
                RepositoryFile repoFile = api.getRepositoryFileApi()
                        .getFile(projectPath, file.getPath(), DEFAULT_BRANCH);

                byte[] content = Base64.getDecoder().decode(repoFile.getContent());
                Path outputFile = outputDir.resolve(file.getName());

                try (FileOutputStream out = new FileOutputStream(outputFile.toFile())) {
                    out.write(content);
                }

                log.info("Saved file: {}", outputFile);
            } catch (Exception e) {
                log.error("Failed to download/save file '{}'", file.getPath(), e);
            }
        }
    }

    String extractProjectPath(String repository) {
        Pattern pattern = Pattern.compile("gitlab\\.com/(.*?)\\.git");
        Matcher matcher = pattern.matcher(repository);
        if (matcher.find()) {
            return matcher.group(1);
        } else {
            throw new IllegalArgumentException("Invalid GitLab repository URL: " + repository);
        }
    }
}
