package de.oaa.xxx.games.chastity.timelock;

import de.oaa.xxx.games.chastity.spinningwheel.EntryType;
import de.oaa.xxx.games.chastity.spinningwheel.SpinningWheelEntry;
import de.oaa.xxx.games.chastity.tasks.Task;
import de.oaa.xxx.games.chastity.tasks.TaskMode;
import de.oaa.xxx.util.ValidationResult;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import java.util.Collections;
import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;

class TimeLockTemplateServiceTest {

    private final TimeLockTemplateService service = new TimeLockTemplateService(null);

    /**
     * Zentrale Factory-Methode für den Test. 
     * Erzeugt immer ein frisches Record-Objekt.
     */
    private TimeLockTemplate createTemplate(
            UUID owner, String name, Integer maxTime, 
            Integer taskEvery, Integer minTasks, List<Task> tasks,
            Integer spinsEvery, Integer minSpins, List<SpinningWheelEntry> entries,
            Integer hygEvery, Integer hygDuration) {
    	return createTemplate(owner, name, maxTime, taskEvery, minTasks, tasks, spinsEvery, minSpins, entries, hygEvery, hygDuration, TaskMode.RANDOM);
    }
    
    private TimeLockTemplate createTemplate(
            UUID owner, String name, Integer maxTime, 
            Integer taskEvery, Integer minTasks, List<Task> tasks,
            Integer spinsEvery, Integer minSpins, List<SpinningWheelEntry> entries,
            Integer hygEvery, Integer hygDuration, TaskMode taskMode) {
        
        return new TimeLockTemplate(null,
                owner,
                name,
                0, // minTimeInMinutes
                maxTime,
                true, // endTimeVisible
                hygDuration,
                hygEvery,
                tasks,
                taskEvery,
                minTasks,
                entries,
                spinsEvery,
                minSpins,
                false, // requiresVerification
                taskMode,
                null, // penaltyType
                null  // penaltyValue
        );
    }

    // Hilfsmethode für ein schnelles Standard-Template
    private TimeLockTemplate validBase() {
        return createTemplate(UUID.randomUUID(), "Standard", 60, null, null, null, null, null, null, null, null);
    }

    @Test
    void validate_OK_Minimal() {
        assertThat(service.validate(validBase())).isEqualTo(ValidationResult.OK);
    }

    @Test
    void validate_ERROR_MissingMandatoryFields() {
        assertThat(service.validate(createTemplate(null, "Name", 10, null, null, null, null, null, null, null, null))).isEqualTo(ValidationResult.ERROR);
        assertThat(service.validate(createTemplate(UUID.randomUUID(), null, 10, null, null, null, null, null, null, null, null))).isEqualTo(ValidationResult.ERROR);
        assertThat(service.validate(createTemplate(UUID.randomUUID(), "Name", null, null, null, null, null, null, null, null, null))).isEqualTo(ValidationResult.ERROR);
    }

    @Test
    void validate_ERROR_TasksButNoList() {
        // Intervall gesetzt, aber Liste ist null oder leer
        TimeLockTemplate tNull = createTemplate(UUID.randomUUID(), "T", 60, 10, null, null, null, null, null, null, null);
        TimeLockTemplate tEmpty = createTemplate(UUID.randomUUID(), "T", 60, 10, null, Collections.emptyList(), null, null, null, null, null);
        
        assertThat(service.validate(tNull)).isEqualTo(ValidationResult.ERROR);
        assertThat(service.validate(tEmpty)).isEqualTo(ValidationResult.ERROR);
    }

    @Test
    void validate_ERROR_SpinningWheelTaskConflict() {
        SpinningWheelEntry taskEntry = new SpinningWheelEntry();
        taskEntry.setType(EntryType.TASK);

        TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, 10, null, List.of(new Task()), null, null, List.of(taskEntry), null, null);
        
        assertThat(service.validate(t)).isEqualTo(ValidationResult.ERROR);
    }

    @Test
    void validate_WARNING_TaskTimeLimitReached() {
        // 120 Min Intervall * 7 Tasks = 840 Min (> 12h)
        TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, 120, 7, List.of(new Task()), null, null, null, null, null);
        
        assertThat(service.validate(t)).isEqualTo(ValidationResult.WARNING);
    }

    @Test
    void validate_ERROR_MinTasksWithoutInterval() {
        TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, null, 5, null, null, null, null, null, null);
        assertThat(service.validate(t)).isEqualTo(ValidationResult.ERROR);
    }

    @Test
    void validate_ERROR_SpinsButNoEntries() {
        TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, null, null, null, 30, 2, null, null, null);
        assertThat(service.validate(t)).isEqualTo(ValidationResult.ERROR);
    }

    @Test
    void validate_WARNING_SpinTimeLimitReached() {
        // 200 Min Intervall * 4 Spins = 800 Min (> 12h)
        TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, null, null, null, 200, 4, List.of(new SpinningWheelEntry()), null, null);
        
        assertThat(service.validate(t)).isEqualTo(ValidationResult.WARNING);
    }

    @Test
    void validate_ERROR_HygieneIncomplete() {
        // Intervall gesetzt, aber Dauer fehlt
        TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, null, null, null, null, null, null, 60, null);
        assertThat(service.validate(t)).isEqualTo(ValidationResult.ERROR);
    }
    
    @Test
    public  void validate_communityVotes() {
        TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, 60, 6, List.of(new Task()), null, null, null, null, null,TaskMode.RANDOM);
        assertThat(service.validate(t)).isEqualTo(ValidationResult.OK);
            
        t = createTemplate(UUID.randomUUID(), "T", 60, 60, 7, List.of(new Task()), null, null, null, null, null,TaskMode.COMMUNITY);
        assertThat(service.validate(t)).isEqualTo(ValidationResult.WARNING);
            
	    t = createTemplate(UUID.randomUUID(), "T", 60, 60, 12, List.of(new Task()), null, null, null, null, null,TaskMode.COMMUNITY);
	    assertThat(service.validate(t)).isEqualTo(ValidationResult.WARNING);
    } 
    
    public void testErrorOnTasksAndTaskInWheel() {
    	SpinningWheelEntry entry = Mockito.mock(SpinningWheelEntry.class);
    	Mockito.when(entry.getType()).thenReturn(EntryType.TASK);
        TimeLockTemplate t = createTemplate(UUID.randomUUID(), "T", 60, 60, 6, List.of(new Task()), null, null, List.of(), null, null);
        assertThat(service.validate(t)).isEqualTo(ValidationResult.ERROR);
    }
}