package ch.zhaw.gartenverwaltung.io;

import ch.zhaw.gartenverwaltung.types.HardinessZone;
import ch.zhaw.gartenverwaltung.types.Plant;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class JsonPlantDatabaseTest {
    PlantDatabase testDatabase;

    @BeforeEach
    void connectToDb() {
        testDatabase = new JsonPlantDatabase();
    }


    @Test
    @DisplayName("Check if results are retrieved completely")
    void getPlantListNotEmpty() {
        List<Plant> testList;
        try {
            testList = testDatabase.getPlantList(HardinessZone.ZONE_8A);
        } catch (IOException | HardinessZoneNotSetException e) {
            throw new RuntimeException(e);
        }
        Assertions.assertEquals(3, testList.size());

        List<String> names = testList.stream().map(Plant::name).collect(Collectors.toList());
        List<String> expected = Arrays.asList("Potato","Early Carrot","Summertime Onion");
        Assertions.assertEquals(expected,names);
    }

    @Test
    @DisplayName("Check if results are retrieved correctly when empty")
    void getPlantListEmpty() {
        List<Plant> testList;
        try {
            testList = testDatabase.getPlantList(HardinessZone.ZONE_1A);
        } catch (IOException | HardinessZoneNotSetException e) {
            throw new RuntimeException(e);
        }
        Assertions.assertEquals(0, testList.size());


    }

    @Test
    @DisplayName("Check whether single access works.")
    void getPlantByIdAndZone() {
        Optional<Plant> testPlant;
        try {
            testPlant = testDatabase.getPlantById(HardinessZone.ZONE_8A, 1);
        } catch (IOException | HardinessZoneNotSetException e) {
            throw new RuntimeException(e);
        }
        Assertions.assertTrue(testPlant.isPresent());
        Assertions.assertEquals("Early Carrot", testPlant.get().name());
    }

    @Test
    @DisplayName("Check whether single access respects zone correctly.")
    void getPlantByIdAndWrongZone() throws HardinessZoneNotSetException, IOException {
        Optional<Plant> testPlant = testDatabase.getPlantById(HardinessZone.ZONE_1A, 1);
        Assertions.assertFalse(testPlant.isPresent());
        testPlant = testDatabase.getPlantById(HardinessZone.ZONE_8A, 1);
        Assertions.assertTrue(testPlant.isPresent());

        Assertions.assertEquals("Early Carrot", testPlant.get().name());
    }

    @Test
    @DisplayName("Check for a nonexisting plant.")
    void getPlantByIdMustFail() {
        Optional<Plant> testPlant;
        try {
            testPlant = testDatabase.getPlantById(HardinessZone.ZONE_8A, 99);
        } catch (IOException | HardinessZoneNotSetException e) {
            throw new RuntimeException(e);
        }
        Assertions.assertFalse(testPlant.isPresent());


    }

}

