///////////////////////////////////////////
///
/// File: FrontendTests.java
/// Author: Evan Gaul
/// Email: eagaul@wisc.edu
/// Date: 9/17/25, 10/22/25
/// Assignment: P103.RoleCode, P107.Integration
/// Course: CS400 Lec004 Fall 2025
/// Professor: Ashley Samuelson
///
///////////////////////////////////////////
///
/// Assistance: None
///
///////////////////////////////////////////

import java.util.Scanner;
import org.junit.Test;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.List;

/**
 * Tests the Frontend class
 * Checks every command is correct
 */
public class FrontendTests {

    /**
     * This test checks the load command and the correct output is outputted from the outputter :)
     */
    @Test
    public void frontendTest1() {
        // load songs.csv, then quit
        TextUITester tester = new TextUITester("load songs.csv\nquit\n");

        Scanner sc = new Scanner(System.in);
        IterableSortedCollection<Song> tree = new RBTreeIterable();
        BackendInterface backend = new Backend(tree);
        Frontend frontend = new Frontend(sc, backend);

        frontend.runCommandLoop();

        String output = tester.checkOutput();

        // check for filename or the word "loaded"
        assertTrue("Frontend should say the filename", output.contains("songs.csv"));
        assertTrue("Frontend should say data was loaded",output.toLowerCase().contains("loaded"));
    }

    /**
     * This test checks the year MIN to MAX and loudness MAX commands are parsed good and give correct output
     */
    @Test
    public void frontendTest2() {
        // year 1990 to 2000, loudness 50, then quit
        TextUITester tester = new TextUITester("year 1990 to 2000\nloudness 50\nquit\n");

        Scanner sc = new Scanner(System.in);
        IterableSortedCollection<Song> tree = new RBTreeIterable();
        BackendInterface backend = new Backend(tree);
        Frontend frontend = new Frontend(sc, backend);

        frontend.runCommandLoop();

        String output = tester.checkOutput();

        assertTrue("Frontend should say both years",output.contains("1990") && output.contains("2000"));
        assertTrue("Frontend should say 'range set'", output.toLowerCase().contains("range set"));
        assertTrue("Frontend should confirm loudness", output.toLowerCase().contains("loudness set"));
    }

    /**
     * This test checks the show most dancable and show commands
     */
    @Test
    public void frontendTest3() {
        // show most danceable, show 3, then quit
        TextUITester tester = new TextUITester("show most danceable\nshow 3\nquit\n");

        Scanner sc = new Scanner(System.in);
        IterableSortedCollection<Song> tree = new RBTreeIterable();
        BackendInterface backend = new Backend(tree);
        Frontend frontend = new Frontend(sc, backend);

        frontend.runCommandLoop();


        String output = tester.checkOutput();

        assertTrue("Frontend should print correct results for 'show most danceable'", output.toLowerCase().contains("most danceable"));
        // check that correct 3 message is there
        assertTrue("Frontend should show right results for 'show 3'", output.contains("Showing 3 songs:"));
    }

    // Integration Tests

    @Test
    public void testInsertAndRetrieveMostDanceable() {
        RBTreeIterable<Song> tree = new RBTreeIterable<>();
        Backend backend = new Backend(tree);

        tree.insert(new Song("A", "X", "Pop", 2020, 100, 80, 90, -4, 5));
        tree.insert(new Song("B", "Y", "Pop", 2021, 100, 80, 50, -4, 5));

        List<String> result = backend.getMostDanceable(1);
        assertEquals(List.of("A"), result);
    }

    @Test
    public void testYearRangeFilter() {
        RBTreeIterable<Song> tree = new RBTreeIterable<>();
        Backend backend = new Backend(tree);

        tree.insert(new Song("Old", "A", "Rock", 1990, 90, 70, 80, -5, 4));
        tree.insert(new Song("New", "B", "Pop", 2020, 95, 75, 85, -3, 5));

        List<String> result = backend.getAndSetRange(2000, 2025);
        assertEquals(List.of("New"), result);
    }

    @Test
    public void testLoudnessFilter() {
        RBTreeIterable<Song> tree = new RBTreeIterable<>();
        Backend backend = new Backend(tree);

        tree.insert(new Song("Quiet", "A", "Jazz", 2010, 80, 60, 70, -8, 3));
        tree.insert(new Song("Loud", "B", "Rock", 2010, 80, 60, 70, -2, 3));

        List<String> result = backend.applyAndSetFilter(-5);
        assertEquals(List.of("Quiet"), result);
    }

    @Test
    public void testFiveMostDanceableLimit() {
        RBTreeIterable<Song> tree = new RBTreeIterable<>();
        Backend backend = new Backend(tree);

        for (int i = 1; i <= 10; i++)
            tree.insert(new Song("Song" + i, "Artist", "Pop", 2020, 100, 80, i * 10, -4, 5));

        List<String> result = backend.fiveMost();
        assertEquals(5, result.size());
    }
}


