package com.magistr.app.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.Column;
import jakarta.persistence.MappedSuperclass;

import java.time.LocalDate;
import java.time.Instant;
import java.time.ZoneId;

@MappedSuperclass
public abstract class LifecycleEntity {

    public static final String STATUS_ACTIVE = "ACTIVE";
    public static final String STATUS_ARCHIVED = "ARCHIVED";

    @Column(name = "status", nullable = false, length = 20)
    private String status = STATUS_ACTIVE;

    @Column(name = "active_from")
    private LocalDate activeFrom;

    @Column(name = "active_to")
    private LocalDate activeTo;

    @Column(name = "archived_at")
    private Instant archivedAt;

    @Column(name = "archive_reason")
    private String archiveReason;

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status == null || status.isBlank() ? STATUS_ACTIVE : status;
    }

    public LocalDate getActiveFrom() {
        return activeFrom;
    }

    public void setActiveFrom(LocalDate activeFrom) {
        this.activeFrom = activeFrom;
    }

    public LocalDate getActiveTo() {
        return activeTo;
    }

    public void setActiveTo(LocalDate activeTo) {
        this.activeTo = activeTo;
    }

    public Instant getArchivedAt() {
        return archivedAt;
    }

    public void setArchivedAt(Instant archivedAt) {
        this.archivedAt = archivedAt;
    }

    public String getArchiveReason() {
        return archiveReason;
    }

    public void setArchiveReason(String archiveReason) {
        this.archiveReason = archiveReason;
    }

    @JsonIgnore
    public boolean isActiveRecord() {
        return !STATUS_ARCHIVED.equals(status);
    }

    @JsonIgnore
    public boolean isArchivedRecord() {
        return STATUS_ARCHIVED.equals(status);
    }

    @JsonIgnore
    public boolean isActiveOn(LocalDate date) {
        if (date == null) {
            return isActiveRecord();
        }
        if (isArchivedRecord() && activeTo == null) {
            return false;
        }
        boolean afterStart = activeFrom == null || !date.isBefore(activeFrom);
        boolean beforeEnd = activeTo == null || !date.isAfter(activeTo);
        return afterStart && beforeEnd;
    }

    public void archive(String reason) {
        archive(reason, LocalDate.now(ZoneId.of("Europe/Moscow")), Instant.now());
    }

    public void archive(String reason, LocalDate businessDate, Instant archiveMoment) {
        status = STATUS_ARCHIVED;
        archivedAt = archiveMoment;
        activeTo = businessDate;
        archiveReason = reason == null || reason.isBlank() ? "Архивировано пользователем" : reason.trim();
    }

    public void restore() {
        status = STATUS_ACTIVE;
        archivedAt = null;
        archiveReason = null;
        activeTo = null;
    }
}
