package ch.zhaw.gartenverwaltung.backgroundtasks.weather;

import ch.zhaw.gartenverwaltung.io.*;
import ch.zhaw.gartenverwaltung.models.PlantNotFoundException;
import ch.zhaw.gartenverwaltung.types.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

import java.io.IOException;
import java.net.URL;
import java.time.LocalDate;
import java.time.MonthDay;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class WeatherGardenTaskPlannerTest {
    private final URL testFile = JsonCropListTest.class.getResource("test-taskdb.json");
    Plant examplePlantOnion;
    Crop exampleCropOnion;
    Task exampleTask;
    Task exampleWeatherTask;
    List<Crop> cropList;
    List<Plant> plantList;
    TaskList taskList;

    @BeforeEach
    void setUp() {
        examplePlantOnion = new Plant(
                20,
                "summertime onion",
                "Onion, (Allium cepa), herbaceous biennial plant in the amaryllis family (Amaryllidaceae) grown for its edible bulb. The onion is likely native to southwestern Asia but is now grown throughout the world, chiefly in the temperate zones. Onions are low in nutrients but are valued for their flavour and are used widely in cooking. They add flavour to such dishes as stews, roasts, soups, and salads and are also served as a cooked vegetable.",
                null,
                "15,30,2",
                0,
                "sandy to loamy, loose soil, free of stones",
                new ArrayList<>(),
                new WateringCycle(15, 3, null),
                List.of(new GrowthPhase(MonthDay.of(6, 4), MonthDay.of(12, 4), 0, GrowthPhaseType.HARVEST, HardinessZone.ZONE_8A, new ArrayList<>()),
                        new GrowthPhase(MonthDay.of(4, 3), MonthDay.of(12, 4), 0, GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>()),
                        new GrowthPhase(MonthDay.of(8, 5), MonthDay.of(12, 4), 0, GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>()),
                        new GrowthPhase(MonthDay.of(2, 8), MonthDay.of(12, 4), 0, GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>()),
                        new GrowthPhase(MonthDay.of(10, 2), MonthDay.of(12, 4), 0, GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>())));

        exampleCropOnion = new Crop(examplePlantOnion.id(), LocalDate.of(2022, 12, 5))
                .withId(3L);
        exampleTask = new Task("water plant","water the plant until the ground is wet enough",LocalDate.now(), LocalDate.now().plusDays(2L),3L);
        exampleTask.setNextExecution(LocalDate.now().plusDays(1L));
        exampleWeatherTask = new Task("Hail",
                "During a summer Thunderstorm it could hail heavily. THe Hail could damage the crops. To prevent damage cover the plants with a strong tarpaulin",
                LocalDate.now(),LocalDate.now().plusDays(1L),3L);

        taskList = new JsonTaskList(testFile);

        plantList = new ArrayList<>();
        plantList.add(examplePlantOnion);

        cropList = new ArrayList<>();
        cropList.add(exampleCropOnion);

    }

    CropList mockCropList(List<Crop> cropList) throws IOException {
        CropList croplist = mock(CropList.class);
        when(croplist.getCrops()).thenReturn(cropList);
        when(croplist.getCropById(3)).thenReturn(java.util.Optional.ofNullable(exampleCropOnion));
        return croplist;
    }

    PlantList mockPlantDatabase(List<Plant> plantList) throws HardinessZoneNotSetException, IOException {
        PlantList plantDatabase = mock(JsonPlantList.class);
        when(plantDatabase.getPlantList(HardinessZone.ZONE_8A)).thenReturn(plantList);
        when(plantDatabase.getPlantById(HardinessZone.ZONE_8A,20)).thenReturn(Optional.of(plantList.get(0)));
        return plantDatabase;
    }

    @Test
    void refreshtasks() throws HardinessZoneNotSetException, IOException, PlantNotFoundException {
        WeatherGradenTaskPlanner weatherGradenTaskPlanner = new WeatherGradenTaskPlanner(taskList, mockPlantDatabase(plantList), mockCropList(cropList));
        taskList.saveTask(exampleTask);
        weatherGradenTaskPlanner.refreshTasks();
        assertEquals(exampleTask.getName(),taskList.getTaskList(LocalDate.now(),LocalDate.now().plusDays(7)).get(0).getName());
        assertEquals(LocalDate.now().plusDays(2L),taskList.getTaskList(LocalDate.now(),LocalDate.now().plusDays(7)).get(0).getNextExecution());
        assertEquals(exampleWeatherTask.getName(),taskList.getTaskList(LocalDate.now(),LocalDate.now().plusDays(7)).get(1).getName());
        assertEquals(exampleWeatherTask.getStartDate(),taskList.getTaskList(LocalDate.now(),LocalDate.now().plusDays(7)).get(1).getStartDate());
    }
}
