import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class FrontendDeveloperTests {

    private FrontendInterface frontend;
    private TextUITester tester;

    @Test
    public void testRunCommandLoop() {
        tester = new TextUITester("Q\n");
        frontend = new Frontend(new Scanner(System.in), new BackendPlaceholder(new ISCPlaceholder<>()));
        frontend.runCommandLoop();
        String actual = tester.checkOutput();
        String expected1 = "~~~ Command Menu ~~~";
        String expected2 = "[R]ead Data";
        String expected3 = "[G]et Songs by Danceability [min - max]";
        String expected4 = "[F]ilter New Songs (by Min Energy: none)";
        String expected5 = "[D]isplay Five Fastest";
        String expected6 = "[Q]uit";
        String expected7 = "Choose command:";
        String expected = """
        ~~~ Command Menu ~~~
            [R]ead Data
            [G]et Songs by Danceability [min - max]
            [F]ilter New Songs (by Min Energy: none)
            [D]isplay Five Fastest
            [Q]uit
        Choose command: """;
        Assertions.assertTrue(actual.contains(expected1));
        Assertions.assertTrue(actual.contains(expected2));
        Assertions.assertTrue(actual.contains(expected3));
        Assertions.assertTrue(actual.contains(expected4));
        Assertions.assertTrue(actual.contains(expected5));
        Assertions.assertTrue(actual.contains(expected6));
        Assertions.assertTrue(actual.contains(expected7));
    }

    @Test
    public void testReadFile() {
        tester = new TextUITester("R\nmySongData.csv\n");
        frontend = new Frontend(new Scanner(System.in), new BackendPlaceholder(new ISCPlaceholder<>()));
        frontend.runCommandLoop();
        String output = tester.checkOutput();
        System.out.println(output);
        String expected1 = "Enter path to csv file to load:";
        String expected2 = "Done reading file.";
        Assertions.assertTrue(output.contains(expected1)&&output.contains(expected2));
    }

    @Test
    public void testReadFileWrongInput() {
        tester = new TextUITester("R\n.csv\n");
        frontend = new Frontend(new Scanner(System.in), new BackendPlaceholder(new ISCPlaceholder<>()));
        frontend.runCommandLoop();
        String output = tester.checkOutput();
        String expect = "Error reading file";
        Assertions.assertTrue(output.contains(expect));
    }

    @Test
    public void testGetValues() {
        tester = new TextUITester("G\n80 - 90\n");
        frontend = new Frontend(new Scanner(System.in), new BackendPlaceholder(new ISCPlaceholder<>()));
        frontend.runCommandLoop();
        String output = tester.checkOutput();
        String expected1 = "Enter range of values (MIN - MAX):";
        String expected2 = "5 songs found between 80 - 90:";
        String expected3 = "Hey, Soul Sister";
        String expected4 = "Love The Way You Lie";
        String expected5 = "Bad Romance";
        String expected6 = "Just the Way You Are";
        Assertions.assertTrue(output.contains(expected1));
        Assertions.assertTrue(output.contains(expected2));
        Assertions.assertTrue(output.contains(expected3));
        Assertions.assertTrue(output.contains(expected4));
        Assertions.assertTrue(output.contains(expected5));
        Assertions.assertTrue(output.contains(expected6));
    }

    @Test
    public void testGetValuesWrongInput1() {
        tester = new TextUITester("G\n - \n");
        frontend = new Frontend(new Scanner(System.in), new BackendPlaceholder(new ISCPlaceholder<>()));
        frontend.runCommandLoop();
        String output = tester.checkOutput();
        Assertions.assertTrue(output.contains("Invalid range. Please try again."));
    }

    @Test
    public void testGetValuesWrongInput2() {
        tester = new TextUITester("G\n - 90\n");
        frontend = new Frontend(new Scanner(System.in), new BackendPlaceholder(new ISCPlaceholder<>()));
        frontend.runCommandLoop();
        String output = tester.checkOutput();
        Assertions.assertTrue(output.contains("Invalid range. Please try again."));
    }

    @Test
    public void testSetFilter() {
        tester = new TextUITester("G\n80 - 90\nF\n85\n");
        frontend = new Frontend(new Scanner(System.in), new BackendPlaceholder(new ISCPlaceholder<>()));
        frontend.runCommandLoop();
        String output = tester.checkOutput();
        String expected1 = "2 songs found between 80  -  90 with energy >= 85";
        String expected2 = "Hey, Soul Sister";
        String expected3 = "Love The Way You Lie";
        Assertions.assertTrue(output.contains(expected1));
        Assertions.assertTrue(output.contains(expected2));
        Assertions.assertTrue(output.contains(expected3));
    }

    @Test
    public void testSetFilterWrongInput() {
        tester = new TextUITester("G\n80 - 90\nF\n-1\n");
        frontend = new Frontend(new Scanner(System.in), new BackendPlaceholder(new ISCPlaceholder<>()));
        frontend.runCommandLoop();
        String output = tester.checkOutput();
        String expected = "Invalid range. Please try again.";
        Assertions.assertTrue(output.contains(expected));
    }

    @Test
    public void testTopFive() {
        tester = new TextUITester("D\n");
        frontend = new Frontend(new Scanner(System.in), new BackendPlaceholder(new ISCPlaceholder<>()));
        frontend.runCommandLoop();
        String output = tester.checkOutput();
        String expected1 = "97: Hey, Soul Sister";
        String expected2 = "87: Love The Way You Lie";
        Assertions.assertTrue(output.contains(expected1));
        Assertions.assertTrue(output.contains(expected2));
    }

    @Test
    public void IntegrationTest1() {
        tester = new TextUITester("R\nmysong.csv\n");
        IterableSortedCollection<SongInterface> songs = new ISCPlaceholder<>();
        frontend = new Frontend(new Scanner(System.in), new Backend(songs));
        frontend.runCommandLoop();
        String output = tester.checkOutput();
        String expected1 = "Enter path to csv file to load:";
        String expected2 = "Error reading file";
        Assertions.assertTrue(output.contains(expected1));
        Assertions.assertTrue(output.contains(expected2));
    }

    @Test
    public void IntegrationTest2() {
        tester = new TextUITester("R\nsong.csv\nG\n50-80\nF\n70\nD\n");
        IterableSortedCollection<SongInterface> songs = new ISCPlaceholder<>();
        frontend = new Frontend(new Scanner(System.in), new Backend(songs));
        frontend.runCommandLoop();
        String output = tester.checkOutput();
        String expected1 = "Top Five songs found between 50 - 80 with energy >= 70:";
        String expected2 = "Love The Way You Lie";
        String expected3 = "TiK ToK";
        String expected4 = "Bad Romance";
        String expected5 = "Baby";
        String expected6 = "Dynamite";
        Assertions.assertTrue(output.contains(expected1));
        Assertions.assertTrue(output.contains(expected2));
        Assertions.assertTrue(output.contains(expected3));
        Assertions.assertTrue(output.contains(expected4));
        Assertions.assertTrue(output.contains(expected5));
        Assertions.assertTrue(output.contains(expected6));
    }
}
