package de.hftstuttgart.dtabackend.utils;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.springframework.stereotype.Component;
import org.springframework.util.FileSystemUtils;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
import org.tmatesoft.svn.core.wc2.SvnCheckout;
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
import org.tmatesoft.svn.core.wc2.SvnTarget;

import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;

@Component
public class RepoUtil {

    private static final Logger LOG = LogManager.getLogger(RepoUtil.class);

    public RepoUtil() {}

    public void cloneRepository(Matcher config, String targetPath, String subDir) {
        if (!config.matches()) {
            LOG.error("Invalid repository URL format.");
            return;
        }

        String repoUrl = config.group(1);
        String username = config.group(2);
        String password = config.group(3);  // Not used for SSH authentication

        LOG.debug("Cloning repository: {}", repoUrl);

        File targetDirectory = new File(targetPath);
        if (targetDirectory.exists()) {
            LOG.debug("Target directory exists, deleting it.");
            FileSystemUtils.deleteRecursively(targetDirectory);
        }

        File checkoutDirectory = targetDirectory;
        if (!subDir.isEmpty()) {
            checkoutDirectory = new File(targetPath + "_checkout");
            if (checkoutDirectory.exists()) {
                LOG.debug("Checkout directory exists, deleting it.");
                FileSystemUtils.deleteRecursively(checkoutDirectory);
            }
        }

        try {
            LOG.debug("Preparing clone...");

            if (repoUrl.endsWith(".git")) {
                // GIT Repository Clone
                CloneCommand cloneCommand = Git.cloneRepository()
                        .setDirectory(checkoutDirectory)
                        .setURI(repoUrl);

                if (!"none".equals(username) && !"none".equals(password)) {
                    LOG.debug("Setting Git credentials.");
                    cloneCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password));
                }

                LOG.debug("Cloning Git repository...");
                cloneCommand.call().close();

            } else {
                // SVN Repository Clone (including svn+ssh support)
                SvnOperationFactory operationFactory = new SvnOperationFactory();
                try {
                    SVNURL svnUrl = SVNURL.parseURIEncoded(repoUrl);
                    SvnCheckout checkout = operationFactory.createCheckout();
                    checkout.setSingleTarget(SvnTarget.fromFile(checkoutDirectory));
                    checkout.setSource(SvnTarget.fromURL(svnUrl));
                    checkout.setDepth(SVNDepth.INFINITY);

                    // **Use SSH authentication if URL starts with svn+ssh://**
                    if (repoUrl.startsWith("svn+ssh://")) {
                        LOG.debug("Setting up SSH authentication for SVN...");

                        String sshPrivateKeyPath = "/home/appuser/.ssh/id_rsa"; 
                        File privateKeyFile = new File(sshPrivateKeyPath);

                        if (!privateKeyFile.exists()) {
                            LOG.error("SSH private key not found at: {}", sshPrivateKeyPath);
                            throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, "SSH key not found"));
                        }

                        ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(
                            new File("/home/appuser/.ssh/id_rsa"),  // Explicit SSH Key
                            username,
                            null,
                            new File("/home/appuser/.ssh/known_hosts"),  // Explicit Known Hosts
                            false
                        );

                        operationFactory.setAuthenticationManager(authManager);
                    }

                    LOG.debug("Performing SVN checkout...");
                    checkout.run();
                } finally {
                    operationFactory.dispose();
                }
            }

            // Handle subdirectory case
            if (!subDir.isEmpty()) {
                File sourceSubDir = new File(checkoutDirectory, subDir);
                if (sourceSubDir.exists()) {
                    FileSystemUtils.copyRecursively(sourceSubDir, targetDirectory);
                } else {
                    LOG.error("Specified subdirectory does not exist.");
                }
            }

            LOG.debug("Repository successfully cloned from {} to {}", repoUrl, targetDirectory);

        } catch (IOException | GitAPIException | SVNException e) {
            LOG.error("Error while cloning repository: " + repoUrl, e);
        }
    }
}