package com.social.media.infrastructure.persistence.entity;

import jakarta.persistence.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

/**
 * JPA Entity for ApiRateLimit aggregate
 */
@Entity
@Table(name = "api_rate_limits",
       uniqueConstraints = @UniqueConstraint(columnNames = {"social_account_id", "endpoint", "window_start"}))
@EntityListeners(AuditingEntityListener.class)
public class ApiRateLimitEntity {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    
    @Column(name = "social_account_id", nullable = false)
    private Long socialAccountId;
    
    @Column(name = "endpoint", nullable = false, length = 100)
    private String endpoint;
    
    @Column(name = "requests_made", nullable = false)
    private Integer requestsMade = 0;
    
    @Column(name = "request_limit", nullable = false)
    private Integer requestLimit;
    
    @Column(name = "window_start", nullable = false)
    private LocalDateTime windowStart;
    
    @Column(name = "window_end", nullable = false)
    private LocalDateTime windowEnd;
    
    @CreatedDate
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;
    
    @LastModifiedDate
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;
    
    // Constructors
    public ApiRateLimitEntity() {}
    
    public ApiRateLimitEntity(Long id, Long socialAccountId, String endpoint, Integer requestsMade,
                             Integer requestLimit, LocalDateTime windowStart, LocalDateTime windowEnd) {
        this.id = id;
        this.socialAccountId = socialAccountId;
        this.endpoint = endpoint;
        this.requestsMade = requestsMade;
        this.requestLimit = requestLimit;
        this.windowStart = windowStart;
        this.windowEnd = windowEnd;
    }
    
    // Business methods
    public boolean isLimitExceeded() {
        return requestsMade >= requestLimit;
    }
    
    public boolean isWindowExpired() {
        return LocalDateTime.now().isAfter(windowEnd);
    }
    
    public void incrementRequests() {
        this.requestsMade++;
    }
    
    public void resetWindow(LocalDateTime newWindowStart, LocalDateTime newWindowEnd) {
        this.windowStart = newWindowStart;
        this.windowEnd = newWindowEnd;
        this.requestsMade = 0;
    }
    
    // Getters and Setters
    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public Long getSocialAccountId() {
        return socialAccountId;
    }
    
    public void setSocialAccountId(Long socialAccountId) {
        this.socialAccountId = socialAccountId;
    }
    
    public String getEndpoint() {
        return endpoint;
    }
    
    public void setEndpoint(String endpoint) {
        this.endpoint = endpoint;
    }
    
    public Integer getRequestsMade() {
        return requestsMade;
    }
    
    public void setRequestsMade(Integer requestsMade) {
        this.requestsMade = requestsMade;
    }
    
    public Integer getRequestLimit() {
        return requestLimit;
    }
    
    public void setRequestLimit(Integer requestLimit) {
        this.requestLimit = requestLimit;
    }
    
    public LocalDateTime getWindowStart() {
        return windowStart;
    }
    
    public void setWindowStart(LocalDateTime windowStart) {
        this.windowStart = windowStart;
    }
    
    public LocalDateTime getWindowEnd() {
        return windowEnd;
    }
    
    public void setWindowEnd(LocalDateTime windowEnd) {
        this.windowEnd = windowEnd;
    }
    
    public LocalDateTime getCreatedAt() {
        return createdAt;
    }
    
    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }
    
    public LocalDateTime getUpdatedAt() {
        return updatedAt;
    }
    
    public void setUpdatedAt(LocalDateTime updatedAt) {
        this.updatedAt = updatedAt;
    }
}
