package de.hftstuttgart.rest.v1.task;

import de.hftstuttgart.config.ModocotProperties;
import de.hftstuttgart.rest.v1.jenkins.RestAPIController;
import de.hftstuttgart.utils.BackendUtil;
import de.hftstuttgart.utils.BuildState;
import de.hftstuttgart.utils.GitTeaUtil;
import de.hftstuttgart.utils.JGitUtil;
import de.hftstuttgart.utils.TaskUploadUtils;
import de.hftstuttgart.utils.UnzipUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.annotation.MultipartConfig;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

/**
 * Rest controller for everything related to the TASK files
 */
@RestController
@RequestMapping("/v1/task")
@MultipartConfig
public class TaskUpload {
    private static final Logger LOG = LogManager.getLogger(TaskUpload.class);

    private final ModocotProperties modocotProperties;
    private final TaskUploadUtils taskUploadUtils;
    private final JGitUtil jGitUtil;
    private final String assignmentBasePath;
    private final GitTeaUtil gitTeaUtil;


    public TaskUpload(ModocotProperties modocotProperties,
                      TaskUploadUtils taskUploadUtils,
                      JGitUtil jGitUtil,
                      GitTeaUtil gitTeaUtil) {
        this.modocotProperties = modocotProperties;
        this.taskUploadUtils = taskUploadUtils;
        this.jGitUtil = jGitUtil;
        this.gitTeaUtil = gitTeaUtil;
        this.assignmentBasePath =
                this.modocotProperties.getModocotParentDirectory()
                        + File.separator
                        + this.modocotProperties.getModocotAssignmentFolderPrefix();
    }

    @RequestMapping(method = RequestMethod.POST)
    public String uploadAndTestFile(@RequestParam("taskFile") MultipartFile taskFileRef,
                                    @RequestParam("assignmentId") String assignmentId) throws IOException, InterruptedException {
        String jobId = assignmentId + "_" + UUID.randomUUID();
        String subFolderPath = this.assignmentBasePath + assignmentId;

        LOG.info("subFolderPath: " + subFolderPath);
        File workDirectory = new File(subFolderPath);
        workDirectory.mkdirs();

        LOG.info("created new File");
        File file = new File(subFolderPath, String.valueOf(UUID.randomUUID()));

        taskFileRef.transferTo(file);
        List<File> unzippedFiles = UnzipUtil.unzip(file);

        if (file.exists()) file.delete();

        startFileRead(assignmentId, subFolderPath, unzippedFiles);

        BuildState buildState = this.taskUploadUtils.startTask(jobId, subFolderPath);

        if (buildState != BuildState.BLUE) {
            String jenkinsError = this.taskUploadUtils.getJenkinsConsoleOutput(jobId);
            LOG.error(jenkinsError);
            RestAPIController.JOB_MAP.remove(jobId);
            this.gitTeaUtil.deleteRepository(jobId);
            this.taskUploadUtils.deleteJenkinsJob(jobId);
            return jenkinsError;
        }

        Thread.sleep(3000);

        String userResult = RestAPIController.JOB_MAP.remove(jobId);

        this.gitTeaUtil.deleteRepository(jobId);

        this.taskUploadUtils.deleteJenkinsJob(jobId);

        if (!this.taskUploadUtils.isValidJSON(userResult)) {
            throw new IllegalArgumentException("userResult from JUnitTestLauncher is invalid: " + userResult);
        }

        return userResult;
    }

    /**
     * Extracting all lines from repo.txt and cloning extracted repository
     *
     * @param assignmentId  String assignmentId
     * @param subFolderPath working-directory
     * @param unzippedFiles List of all Files from {@link MultipartFile}
     */
    private void startFileRead(String assignmentId, String subFolderPath, List<File> unzippedFiles) {
        boolean gotRepoFile = unzippedFiles.stream().anyMatch(zipFile -> zipFile.getName().equalsIgnoreCase("repo.txt"));
        if (gotRepoFile) {
            List<String> lines = BackendUtil.extractLinesFromRepoFile(unzippedFiles, "repo.txt");
            String repoUrl = (lines.size() > 0 && !lines.get(0).equals("")) ?
                    lines.get(0) : "";
            String credentials = (lines.size() > 1 && !lines.get(1).equals("")) ?
                    lines.get(1) : null;
            File unit = new File(subFolderPath + "/src/UnitTests");
            unit.mkdirs();
            File task = new File(subFolderPath + "/src/Test");
            task.mkdirs();

            this.jGitUtil.cloneRepository("http://" + this.modocotProperties.getDockerHostIp()
                    + ":3000/" + this.modocotProperties.getGitTeaUsername() + "/"
                    + assignmentId + ".git",
                    unit, null, true, false);
            this.jGitUtil.cloneRepository(repoUrl, task, credentials, credentials != null, true);
        }
    }
}
