package dev.lions.unionflow.server.entity;

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

import java.time.LocalDateTime;
import java.util.UUID;

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

@DisplayName("BackupConfig")
class BackupConfigTest {

    // -------------------------------------------------------------------------
    // No-args constructor
    // -------------------------------------------------------------------------

    @Test
    @DisplayName("no-args constructor creates non-null instance")
    void noArgsConstructor() {
        BackupConfig cfg = new BackupConfig();
        assertThat(cfg).isNotNull();
    }

    @Test
    @DisplayName("no-args constructor: @Builder.Default fields are null without builder")
    void noArgsConstructor_builderDefaultFieldsAreNull() {
        // Lombok @Builder.Default with @NoArgsConstructor leaves fields at their
        // Java-primitive defaults (null for boxed types) unless a plain field
        // initializer is present. BackupConfig uses @Builder.Default, so
        // no-args ctor produces null for those fields.
        BackupConfig cfg = new BackupConfig();
        assertThat(cfg.getAutoBackupEnabled()).isNull();
        assertThat(cfg.getFrequency()).isNull();
        assertThat(cfg.getRetentionDays()).isNull();
        assertThat(cfg.getBackupTime()).isNull();
        assertThat(cfg.getIncludeDatabase()).isNull();
        assertThat(cfg.getIncludeFiles()).isNull();
        assertThat(cfg.getIncludeConfiguration()).isNull();
    }

    // -------------------------------------------------------------------------
    // Builder — defaults
    // -------------------------------------------------------------------------

    @Test
    @DisplayName("builder applies @Builder.Default values when fields not set")
    void builder_defaults() {
        BackupConfig cfg = BackupConfig.builder().build();

        assertThat(cfg.getAutoBackupEnabled()).isTrue();
        assertThat(cfg.getFrequency()).isEqualTo("DAILY");
        assertThat(cfg.getRetentionDays()).isEqualTo(30);
        assertThat(cfg.getBackupTime()).isEqualTo("02:00");
        assertThat(cfg.getIncludeDatabase()).isTrue();
        assertThat(cfg.getIncludeFiles()).isFalse();
        assertThat(cfg.getIncludeConfiguration()).isTrue();
        assertThat(cfg.getBackupDirectory()).isNull();
    }

    // -------------------------------------------------------------------------
    // Builder — override all fields
    // -------------------------------------------------------------------------

    @Test
    @DisplayName("builder overrides all @Builder.Default values")
    void builder_overrideAllDefaults() {
        BackupConfig cfg = BackupConfig.builder()
                .autoBackupEnabled(false)
                .frequency("WEEKLY")
                .retentionDays(90)
                .backupTime("03:30")
                .includeDatabase(false)
                .includeFiles(true)
                .includeConfiguration(false)
                .backupDirectory("/var/backups/unionflow")
                .build();

        assertThat(cfg.getAutoBackupEnabled()).isFalse();
        assertThat(cfg.getFrequency()).isEqualTo("WEEKLY");
        assertThat(cfg.getRetentionDays()).isEqualTo(90);
        assertThat(cfg.getBackupTime()).isEqualTo("03:30");
        assertThat(cfg.getIncludeDatabase()).isFalse();
        assertThat(cfg.getIncludeFiles()).isTrue();
        assertThat(cfg.getIncludeConfiguration()).isFalse();
        assertThat(cfg.getBackupDirectory()).isEqualTo("/var/backups/unionflow");
    }

    @Test
    @DisplayName("builder: HOURLY frequency")
    void builder_hourlyFrequency() {
        BackupConfig cfg = BackupConfig.builder()
                .frequency("HOURLY")
                .retentionDays(7)
                .build();
        assertThat(cfg.getFrequency()).isEqualTo("HOURLY");
        assertThat(cfg.getRetentionDays()).isEqualTo(7);
    }

    // -------------------------------------------------------------------------
    // All-args constructor
    // -------------------------------------------------------------------------

    @Test
    @DisplayName("all-args constructor populates every field")
    void allArgsConstructor() {
        BackupConfig cfg = new BackupConfig(true, "DAILY", 30, "02:00", true, false, true, "/data/backup");

        assertThat(cfg.getAutoBackupEnabled()).isTrue();
        assertThat(cfg.getFrequency()).isEqualTo("DAILY");
        assertThat(cfg.getRetentionDays()).isEqualTo(30);
        assertThat(cfg.getBackupTime()).isEqualTo("02:00");
        assertThat(cfg.getIncludeDatabase()).isTrue();
        assertThat(cfg.getIncludeFiles()).isFalse();
        assertThat(cfg.getIncludeConfiguration()).isTrue();
        assertThat(cfg.getBackupDirectory()).isEqualTo("/data/backup");
    }

    // -------------------------------------------------------------------------
    // Getters / Setters (@Data)
    // -------------------------------------------------------------------------

    @Test
    @DisplayName("setters and getters round-trip")
    void settersGetters() {
        BackupConfig cfg = new BackupConfig();

        cfg.setAutoBackupEnabled(true);
        cfg.setFrequency("DAILY");
        cfg.setRetentionDays(60);
        cfg.setBackupTime("04:00");
        cfg.setIncludeDatabase(true);
        cfg.setIncludeFiles(true);
        cfg.setIncludeConfiguration(false);
        cfg.setBackupDirectory("/mnt/nas/backups");

        assertThat(cfg.getAutoBackupEnabled()).isTrue();
        assertThat(cfg.getFrequency()).isEqualTo("DAILY");
        assertThat(cfg.getRetentionDays()).isEqualTo(60);
        assertThat(cfg.getBackupTime()).isEqualTo("04:00");
        assertThat(cfg.getIncludeDatabase()).isTrue();
        assertThat(cfg.getIncludeFiles()).isTrue();
        assertThat(cfg.getIncludeConfiguration()).isFalse();
        assertThat(cfg.getBackupDirectory()).isEqualTo("/mnt/nas/backups");
    }

    @Test
    @DisplayName("backupDirectory accepts null")
    void backupDirectoryNull() {
        BackupConfig cfg = BackupConfig.builder().build();
        cfg.setBackupDirectory(null);
        assertThat(cfg.getBackupDirectory()).isNull();
    }

    // -------------------------------------------------------------------------
    // BaseEntity fields
    // -------------------------------------------------------------------------

    @Test
    @DisplayName("BaseEntity fields accessible via inherited getters/setters")
    void baseEntityFields() {
        BackupConfig cfg = new BackupConfig();
        UUID id = UUID.randomUUID();
        LocalDateTime now = LocalDateTime.now();

        cfg.setId(id);
        cfg.setDateCreation(now);
        cfg.setDateModification(now);
        cfg.setCreePar("system@test.com");
        cfg.setModifiePar("admin@test.com");
        cfg.setVersion(3L);
        cfg.setActif(false);

        assertThat(cfg.getId()).isEqualTo(id);
        assertThat(cfg.getDateCreation()).isEqualTo(now);
        assertThat(cfg.getDateModification()).isEqualTo(now);
        assertThat(cfg.getCreePar()).isEqualTo("system@test.com");
        assertThat(cfg.getModifiePar()).isEqualTo("admin@test.com");
        assertThat(cfg.getVersion()).isEqualTo(3L);
        assertThat(cfg.getActif()).isFalse();
    }

    // -------------------------------------------------------------------------
    // equals / hashCode / toString  (@Data + @EqualsAndHashCode(callSuper = true))
    // -------------------------------------------------------------------------

    @Test
    @DisplayName("equals and hashCode are consistent for identical content")
    void equalsHashCode() {
        BackupConfig a = BackupConfig.builder()
                .frequency("DAILY")
                .retentionDays(30)
                .build();
        BackupConfig b = BackupConfig.builder()
                .frequency("DAILY")
                .retentionDays(30)
                .build();

        // Both have null id (BaseEntity), so equals based on field values
        assertThat(a).isEqualTo(b);
        assertThat(a.hashCode()).isEqualTo(b.hashCode());
    }

    @Test
    @DisplayName("equals returns false for different frequency")
    void equalsReturnsFalseForDifferentFrequency() {
        BackupConfig a = BackupConfig.builder().frequency("DAILY").build();
        BackupConfig b = BackupConfig.builder().frequency("WEEKLY").build();
        assertThat(a).isNotEqualTo(b);
    }

    @Test
    @DisplayName("toString is non-null and non-empty")
    void toStringNonNull() {
        BackupConfig cfg = BackupConfig.builder().build();
        assertThat(cfg.toString()).isNotNull().isNotEmpty();
    }
}
