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("BackupRecord")
class BackupRecordTest {

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

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

    @Test
    @DisplayName("no-args constructor: @Builder.Default fields are null (no builder involved)")
    void noArgsConstructor_builderDefaultFieldsAreNull() {
        BackupRecord rec = new BackupRecord();
        // @Builder.Default means the no-arg ctor leaves these as null
        assertThat(rec.getIncludesDatabase()).isNull();
        assertThat(rec.getIncludesFiles()).isNull();
        assertThat(rec.getIncludesConfiguration()).isNull();
    }

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

    @Test
    @DisplayName("builder applies @Builder.Default values: includesDatabase=true, includesFiles=false, includesConfiguration=true")
    void builder_defaults() {
        BackupRecord rec = BackupRecord.builder()
                .name("backup-2026-03-15")
                .type("AUTO")
                .status("COMPLETED")
                .build();

        assertThat(rec.getIncludesDatabase()).isTrue();
        assertThat(rec.getIncludesFiles()).isFalse();
        assertThat(rec.getIncludesConfiguration()).isTrue();
    }

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

    @Test
    @DisplayName("builder sets every field when all are provided")
    void builder_allFields() {
        LocalDateTime completedAt = LocalDateTime.of(2026, 3, 15, 3, 0, 45);

        BackupRecord rec = BackupRecord.builder()
                .name("backup-manual-2026-03-15")
                .description("Pre-migration snapshot")
                .type("MANUAL")
                .sizeBytes(524288000L)
                .status("COMPLETED")
                .completedAt(completedAt)
                .createdBy("admin@unionflow.test")
                .includesDatabase(true)
                .includesFiles(true)
                .includesConfiguration(true)
                .filePath("/var/backups/unionflow/backup-manual-2026-03-15.tar.gz")
                .errorMessage(null)
                .build();

        assertThat(rec.getName()).isEqualTo("backup-manual-2026-03-15");
        assertThat(rec.getDescription()).isEqualTo("Pre-migration snapshot");
        assertThat(rec.getType()).isEqualTo("MANUAL");
        assertThat(rec.getSizeBytes()).isEqualTo(524288000L);
        assertThat(rec.getStatus()).isEqualTo("COMPLETED");
        assertThat(rec.getCompletedAt()).isEqualTo(completedAt);
        assertThat(rec.getCreatedBy()).isEqualTo("admin@unionflow.test");
        assertThat(rec.getIncludesDatabase()).isTrue();
        assertThat(rec.getIncludesFiles()).isTrue();
        assertThat(rec.getIncludesConfiguration()).isTrue();
        assertThat(rec.getFilePath()).isEqualTo("/var/backups/unionflow/backup-manual-2026-03-15.tar.gz");
        assertThat(rec.getErrorMessage()).isNull();
    }

    @Test
    @DisplayName("builder: RESTORE_POINT type")
    void builder_restorePoint() {
        BackupRecord rec = BackupRecord.builder()
                .name("restore-point-001")
                .type("RESTORE_POINT")
                .status("COMPLETED")
                .build();
        assertThat(rec.getType()).isEqualTo("RESTORE_POINT");
    }

    @Test
    @DisplayName("builder: IN_PROGRESS status and no completedAt")
    void builder_inProgress() {
        BackupRecord rec = BackupRecord.builder()
                .name("backup-in-progress")
                .type("AUTO")
                .status("IN_PROGRESS")
                .build();
        assertThat(rec.getStatus()).isEqualTo("IN_PROGRESS");
        assertThat(rec.getCompletedAt()).isNull();
    }

    @Test
    @DisplayName("builder: FAILED status with errorMessage")
    void builder_failed() {
        BackupRecord rec = BackupRecord.builder()
                .name("backup-failed")
                .type("AUTO")
                .status("FAILED")
                .errorMessage("Disk quota exceeded")
                .build();
        assertThat(rec.getStatus()).isEqualTo("FAILED");
        assertThat(rec.getErrorMessage()).isEqualTo("Disk quota exceeded");
    }

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

    @Test
    @DisplayName("all-args constructor populates every field")
    void allArgsConstructor() {
        LocalDateTime completedAt = LocalDateTime.of(2026, 1, 1, 2, 5);

        BackupRecord rec = new BackupRecord(
                "daily-backup",
                "Automated daily backup",
                "AUTO",
                1048576L,
                "COMPLETED",
                completedAt,
                "scheduler",
                true,
                false,
                true,
                "/backups/daily.tar.gz",
                null
        );

        assertThat(rec.getName()).isEqualTo("daily-backup");
        assertThat(rec.getDescription()).isEqualTo("Automated daily backup");
        assertThat(rec.getType()).isEqualTo("AUTO");
        assertThat(rec.getSizeBytes()).isEqualTo(1048576L);
        assertThat(rec.getStatus()).isEqualTo("COMPLETED");
        assertThat(rec.getCompletedAt()).isEqualTo(completedAt);
        assertThat(rec.getCreatedBy()).isEqualTo("scheduler");
        assertThat(rec.getIncludesDatabase()).isTrue();
        assertThat(rec.getIncludesFiles()).isFalse();
        assertThat(rec.getIncludesConfiguration()).isTrue();
        assertThat(rec.getFilePath()).isEqualTo("/backups/daily.tar.gz");
        assertThat(rec.getErrorMessage()).isNull();
    }

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

    @Test
    @DisplayName("setters and getters round-trip for all fields")
    void settersGetters() {
        BackupRecord rec = new BackupRecord();
        LocalDateTime completedAt = LocalDateTime.of(2026, 4, 1, 5, 0);

        rec.setName("weekly-backup");
        rec.setDescription("Weekly archive");
        rec.setType("AUTO");
        rec.setSizeBytes(2097152L);
        rec.setStatus("COMPLETED");
        rec.setCompletedAt(completedAt);
        rec.setCreatedBy("admin");
        rec.setIncludesDatabase(true);
        rec.setIncludesFiles(false);
        rec.setIncludesConfiguration(true);
        rec.setFilePath("/archives/weekly.tar.gz");
        rec.setErrorMessage(null);

        assertThat(rec.getName()).isEqualTo("weekly-backup");
        assertThat(rec.getDescription()).isEqualTo("Weekly archive");
        assertThat(rec.getType()).isEqualTo("AUTO");
        assertThat(rec.getSizeBytes()).isEqualTo(2097152L);
        assertThat(rec.getStatus()).isEqualTo("COMPLETED");
        assertThat(rec.getCompletedAt()).isEqualTo(completedAt);
        assertThat(rec.getCreatedBy()).isEqualTo("admin");
        assertThat(rec.getIncludesDatabase()).isTrue();
        assertThat(rec.getIncludesFiles()).isFalse();
        assertThat(rec.getIncludesConfiguration()).isTrue();
        assertThat(rec.getFilePath()).isEqualTo("/archives/weekly.tar.gz");
        assertThat(rec.getErrorMessage()).isNull();
    }

    @Test
    @DisplayName("optional fields accept null")
    void optionalFieldsAcceptNull() {
        BackupRecord rec = new BackupRecord();
        rec.setDescription(null);
        rec.setSizeBytes(null);
        rec.setCompletedAt(null);
        rec.setCreatedBy(null);
        rec.setFilePath(null);
        rec.setErrorMessage(null);

        assertThat(rec.getDescription()).isNull();
        assertThat(rec.getSizeBytes()).isNull();
        assertThat(rec.getCompletedAt()).isNull();
        assertThat(rec.getCreatedBy()).isNull();
        assertThat(rec.getFilePath()).isNull();
        assertThat(rec.getErrorMessage()).isNull();
    }

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

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

        rec.setId(id);
        rec.setDateCreation(now);
        rec.setDateModification(now);
        rec.setCreePar("system");
        rec.setModifiePar("operator");
        rec.setVersion(5L);
        rec.setActif(true);

        assertThat(rec.getId()).isEqualTo(id);
        assertThat(rec.getDateCreation()).isEqualTo(now);
        assertThat(rec.getDateModification()).isEqualTo(now);
        assertThat(rec.getCreePar()).isEqualTo("system");
        assertThat(rec.getModifiePar()).isEqualTo("operator");
        assertThat(rec.getVersion()).isEqualTo(5L);
        assertThat(rec.getActif()).isTrue();
    }

    // -------------------------------------------------------------------------
    // equals / hashCode / toString
    // -------------------------------------------------------------------------

    @Test
    @DisplayName("equals and hashCode consistent for identical content")
    void equalsHashCode() {
        BackupRecord a = BackupRecord.builder()
                .name("rec-A")
                .type("AUTO")
                .status("COMPLETED")
                .build();
        BackupRecord b = BackupRecord.builder()
                .name("rec-A")
                .type("AUTO")
                .status("COMPLETED")
                .build();

        assertThat(a).isEqualTo(b);
        assertThat(a.hashCode()).isEqualTo(b.hashCode());
    }

    @Test
    @DisplayName("equals returns false for different name")
    void equalsReturnsFalseForDifferentName() {
        BackupRecord a = BackupRecord.builder().name("alpha").type("AUTO").status("COMPLETED").build();
        BackupRecord b = BackupRecord.builder().name("beta").type("AUTO").status("COMPLETED").build();
        assertThat(a).isNotEqualTo(b);
    }

    @Test
    @DisplayName("toString is non-null and non-empty")
    void toStringNonNull() {
        BackupRecord rec = BackupRecord.builder()
                .name("test")
                .type("MANUAL")
                .status("COMPLETED")
                .build();
        assertThat(rec.toString()).isNotNull().isNotEmpty();
    }
}
