package com.example.demo.controller;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

import static org.junit.Assert.*;

@RunWith(MockitoJUnitRunner.class)
public class MainControllerTest {

    private final MainController mainController = new MainController();

    @Test
    public void testExtractRepoName_ValidURL() {
        String url = "https://github.com/user/repo";
        String expected = "repo";
        String actual = mainController.extractRepoName(url);
        assertEquals(expected, actual);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testExtractRepoName_InvalidURL() {
        String url = "invalid_url";
        mainController.extractRepoName(url);
    }

    @Test
    public void testDownloadFile_ValidURL() throws IOException {
        String fileURL = "https://github.com/Kev9794/modul3/archive/refs/heads/main.zip";
        String destination = "tempFile.zip";
        MainController.downloadFile(fileURL, destination);
        assertTrue(Files.exists(Paths.get(destination)));
        Files.delete(Paths.get(destination)); // Cleanup
    }

    @Test(expected = IOException.class)
    public void testDownloadFile_InvalidURL() throws IOException {
        String fileURL = "invalid_url";
        String destination = "tempFile.zip";
        MainController.downloadFile(fileURL, destination);
    }

    @Test
    public void testUnzip_ValidFile() throws IOException {
        String zipFilePath = "testDir//test.zip";
        String destDirectory = "testDir";
        // Assume the zip file exists and contains valid data for the test
        MainController.unzip(zipFilePath, destDirectory);
        assertTrue(Files.exists(Paths.get(destDirectory)));
        // Cleanup
        Files.walk(Paths.get(destDirectory))
                .sorted(Comparator.reverseOrder())
                .map(Path::toFile)
                .forEach(File::delete);
        Files.deleteIfExists(Paths.get(zipFilePath));
    }

    @Test(expected = IOException.class)
    public void testUnzip_InvalidFile() throws IOException {
        String zipFilePath = "invalid.zip";
        String destDirectory = "testDir";
        MainController.unzip(zipFilePath, destDirectory);
    }

    @Test
    public void testCopyDirectory() throws IOException {
        Path sourceDir = Files.createTempDirectory("sourceDir");
        Path destinationDir = Files.createTempDirectory("destinationDir");

        Files.createFile(sourceDir.resolve("testFile.txt"));

        MainController.copyDirectory(sourceDir.toFile(), destinationDir.toFile());

        assertTrue(Files.exists(destinationDir.resolve("testFile.txt")));

        // Cleanup
        Files.walk(sourceDir).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
        Files.walk(destinationDir).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
    }

    @Test
    public void testRunFlutterTest() throws IOException {
        String projectDir = "C:\\Users\\kevin\\Desktop\\Materi kuliah\\SKRIPSI\\flutter_testing_app";
        // Assume the Flutter project exists at the specified path
        String output = MainController.runFlutterTest(projectDir);
        assertNotNull(output);
        assertTrue(output.contains("All tests passed") || output.contains("Some tests failed"));
    }

    @Test
    public void testParseSuccessTestOutput() {
        String testOutput = "00:17 +42 -2: C:/Users/kevin/Desktop/Materi kuliah/SKRIPSI/unzipped/media_player_flutter_failed-main/test/scenario/task3a_test.dart: All tests passed";
        List<String> successTests = new ArrayList<>();
        List<String> failedTests = new ArrayList<>();
        MainController.parseTestOutput(testOutput, successTests, failedTests);

        assertTrue(successTests.contains("All tests passed"));
    }

    @Test
    public void testParseFailedTestOutput() {
        String testOutput = "00:17 +42 -2: C:/Users/kevin/Desktop/Materi kuliah/SKRIPSI/unzipped/media_player_flutter_failed-main/test/scenario/task3a_test.dart: Some tests failed [E]";
        List<String> successTests = new ArrayList<>();
        List<String> failedTests = new ArrayList<>();
        MainController.parseTestOutput(testOutput, successTests, failedTests);

        assertTrue(failedTests.contains("Some tests failed"));
    }

    // @Test
    // public void testLoad() throws InterruptedException {
    // int numberOfRequests = 100;
    // ExecutorService executorService = Executors.newFixedThreadPool(10);
    // List<Future<ResponseEntity<Map<String, Object>>>> futures = new
    // ArrayList<>();

    // for (int i = 0; i < numberOfRequests; i++) {
    // Future<ResponseEntity<Map<String, Object>>> future =
    // executorService.submit(() -> {
    // String fileURL = "https://github.com/user/repo/archive/refs/heads/main.zip";
    // String flutterid = "testFlutterID";
    // return mainController.submit(fileURL, flutterid);
    // });
    // futures.add(future);
    // }

    // for (Future<ResponseEntity<Map<String, Object>>> future : futures) {
    // try {
    // ResponseEntity<Map<String, Object>> response = future.get();
    // assertEquals(HttpStatus.OK, response.getStatusCode());
    // } catch (ExecutionException e) {
    // e.printStackTrace();
    // }
    // }

    // executorService.shutdown();
    // executorService.awaitTermination(1, TimeUnit.MINUTES);
    // }

    // @Test
    // public void testStress() throws InterruptedException {
    // int numberOfRequests = 1000; // Increase until failureS
    // ExecutorService executorService = Executors.newFixedThreadPool(50);
    // List<Future<ResponseEntity<Map<String, Object>>>> futures = new
    // ArrayList<>();

    // for (int i = 0; i < numberOfRequests; i++) {
    // Future<ResponseEntity<Map<String, Object>>> future =
    // executorService.submit(() -> {
    // String fileURL = "https://github.com/user/repo/archive/refs/heads/main.zip";
    // String flutterid = "testFlutterID";
    // return mainController.submit(fileURL, flutterid);
    // });
    // futures.add(future);
    // }

    // for (Future<ResponseEntity<Map<String, Object>>> future : futures) {
    // try {
    // ResponseEntity<Map<String, Object>> response = future.get();
    // assertEquals(HttpStatus.OK, response.getStatusCode());
    // } catch (ExecutionException e) {
    // e.printStackTrace();
    // }
    // }

    // executorService.shutdown();
    // executorService.awaitTermination(1, TimeUnit.MINUTES);
    // }

    // @Test
    // public void testEndurance() throws InterruptedException {
    // int durationInMinutes = 2; // 2 minutes for endurance test
    // long endTime = System.currentTimeMillis() + (durationInMinutes * 60 * 1000);
    // ExecutorService executorService = Executors.newFixedThreadPool(10);

    // while (System.currentTimeMillis() < endTime) {
    // Future<ResponseEntity<Map<String, Object>>> future =
    // executorService.submit(() -> {
    // String fileURL = "https://github.com/user/repo/archive/refs/heads/main.zip";
    // String flutterid = "testFlutterID";
    // return mainController.submit(fileURL, flutterid);
    // });

    // try {
    // ResponseEntity<Map<String, Object>> response = future.get();
    // assertEquals(HttpStatus.OK, response.getStatusCode());
    // } catch (ExecutionException e) {
    // e.printStackTrace();
    // }
    // }

    // executorService.shutdown();
    // executorService.awaitTermination(10, TimeUnit.MINUTES);
    // }

    // @Test
    // public void testThroughput() throws InterruptedException {
    // int numberOfRequests = 50;
    // long startTime = System.currentTimeMillis();
    // ExecutorService executorService = Executors.newFixedThreadPool(50);
    // List<Future<ResponseEntity<Map<String, Object>>>> futures = new
    // ArrayList<>();

    // for (int i = 0; i < numberOfRequests; i++) {
    // Future<ResponseEntity<Map<String, Object>>> future =
    // executorService.submit(() -> {
    // String fileURL = "https://github.com/user/repo/archive/refs/heads/main.zip";
    // String flutterid = "testFlutterID";
    // return mainController.submit(fileURL, flutterid);
    // });
    // futures.add(future);
    // }

    // for (Future<ResponseEntity<Map<String, Object>>> future : futures) {
    // try {
    // ResponseEntity<Map<String, Object>> response = future.get();
    // assertEquals(HttpStatus.OK, response.getStatusCode());
    // } catch (ExecutionException e) {
    // e.printStackTrace();
    // }
    // }

    // long endTime = System.currentTimeMillis();
    // long duration = endTime - startTime;
    // double throughput = (double) numberOfRequests / (duration / 1000.0);
    // System.out.println("Throughput: " + throughput + " requests per second");

    // executorService.shutdown();
    // executorService.awaitTermination(1, TimeUnit.MINUTES);
    // }
}