package at.procon.ted.model.entity;

import jakarta.persistence.*;
import lombok.*;
import java.time.OffsetDateTime;
import java.util.UUID;

/**
 * JPA Entity for tracking downloaded TED Daily Packages.
 *
 * Stores information about each downloaded package to ensure idempotency
 * and track download progress.
 *
 * @author Martin.Schweitzer@procon.co.at and claude.ai
 */
@Entity
@Table(name = "ted_daily_package", indexes = {
    @Index(name = "idx_package_identifier", columnList = "packageIdentifier", unique = true),
    @Index(name = "idx_package_year_serial", columnList = "year,serialNumber", unique = true),
    @Index(name = "idx_package_status", columnList = "downloadStatus"),
    @Index(name = "idx_package_downloaded_at", columnList = "downloadedAt")
})
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class TedDailyPackage {

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

    /**
     * Package identifier in format YYYYSSSSS (e.g. 202400001)
     */
    @Column(name = "package_identifier", nullable = false, unique = true, length = 20)
    private String packageIdentifier;

    /**
     * Year of the package (e.g. 2024)
     */
    @Column(name = "year", nullable = false)
    private Integer year;

    /**
     * Serial number within the year (e.g. 1, 2, 3...)
     */
    @Column(name = "serial_number", nullable = false)
    private Integer serialNumber;

    /**
     * Download URL
     */
    @Column(name = "download_url", nullable = false, length = 500)
    private String downloadUrl;

    /**
     * SHA-256 hash of the downloaded tar.gz file
     */
    @Column(name = "file_hash", length = 64)
    private String fileHash;

    /**
     * Number of extracted XML files
     */
    @Column(name = "xml_file_count")
    private Integer xmlFileCount;

    /**
     * Number of successfully processed documents
     */
    @Column(name = "processed_count")
    @Builder.Default
    private Integer processedCount = 0;

    /**
     * Number of failed documents
     */
    @Column(name = "failed_count")
    @Builder.Default
    private Integer failedCount = 0;

    /**
     * Download status
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "download_status", nullable = false, length = 30)
    @Builder.Default
    private DownloadStatus downloadStatus = DownloadStatus.PENDING;

    /**
     * Error message for failed download
     */
    @Column(name = "error_message", columnDefinition = "TEXT")
    private String errorMessage;

    /**
     * Timestamp of successful download
     */
    @Column(name = "downloaded_at")
    private OffsetDateTime downloadedAt;

    /**
     * Timestamp of complete processing
     */
    @Column(name = "processed_at")
    private OffsetDateTime processedAt;

    /**
     * Download duration in milliseconds
     */
    @Column(name = "download_duration_ms")
    private Long downloadDurationMs;

    /**
     * Processing duration in milliseconds
     */
    @Column(name = "processing_duration_ms")
    private Long processingDurationMs;

    /**
     * Timestamp of creation
     */
    @Column(name = "created_at", nullable = false)
    @Builder.Default
    private OffsetDateTime createdAt = OffsetDateTime.now();

    /**
     * Timestamp of last update
     */
    @Column(name = "updated_at", nullable = false)
    @Builder.Default
    private OffsetDateTime updatedAt = OffsetDateTime.now();

    /**
     * Download status enum
     */
    public enum DownloadStatus {
        PENDING,        // Not yet downloaded
        DOWNLOADING,    // Download in progress
        DOWNLOADED,     // Downloaded, not processed
        PROCESSING,     // Being processed
        COMPLETED,      // Fully processed
        FAILED,         // Download or processing failed
        NOT_FOUND       // Package does not exist (404)
    }

    @PrePersist
    protected void onCreate() {
        if (createdAt == null) {
            createdAt = OffsetDateTime.now();
        }
        if (updatedAt == null) {
            updatedAt = OffsetDateTime.now();
        }
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = OffsetDateTime.now();
    }
}
