package ru.soune.nocopy.entity.user;

import jakarta.persistence.*;
import lombok.*;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;

@Entity
@Table(name = "protect_check")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EntityListeners(AuditingEntityListener.class)
public class ProtectedFileCheck {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", unique = true, nullable = false)
    private User user;

    @Column(nullable = false)
    @Builder.Default
    private Integer countChecked = 0;

    @Column(name = "last_check_at")
    private LocalDateTime lastCheckAt;

    @Version
    private Long version;

    @ElementCollection
    @CollectionTable(
            name = "protection_usage_by_type",
            joinColumns = @JoinColumn(name = "protection_usage_id"))
    @MapKeyColumn(name = "file_type")
    @Column(name = "count")
    @Builder.Default
    private Map<String, Integer> usageByType = new HashMap<>();

    @Column(name = "period_start_date")
    @Builder.Default
    private LocalDate periodStartDate = LocalDate.now();

    @Column(name = "period_count")
    @Builder.Default
    private Integer periodCount = 0;

    public synchronized boolean writeCheck(String fileType) {
        resetPeriodIfNeeded();

        countChecked++;
        periodCount++;

        usageByType.merge(fileType, 1, Integer::sum);

        lastCheckAt = LocalDateTime.now();

        return true;
    }

    private void resetPeriodIfNeeded() {
        LocalDate today = LocalDate.now();

        if (periodStartDate == null ||
                ChronoUnit.DAYS.between(periodStartDate, today) >= 30) {

            cleanupOldData();

            periodStartDate = today;
            periodCount = 0;
        }
    }

    public void cleanupOldData() {
        if (usageByType != null && !usageByType.isEmpty()) {
            usageByType.clear();
            periodCount = 0;
        }

        lastCheckAt = LocalDateTime.now();
    }


    public int getPeriodCount() {
        resetPeriodIfNeeded();
        return periodCount;
    }

    public LocalDate getPeriodStartDate() {
        resetPeriodIfNeeded();
        return periodStartDate;
    }
}