package cn.yunzhixue.ability.center.examsprint.domain.report;

import cn.yunzhixue.ability.center.examsprint.contracts.report.ExamSprintReportGenerationStatus;
import cn.yunzhixue.ability.center.examsprint.contracts.report.ExamSprintReportType;
import com.fasterxml.jackson.databind.JsonNode;

import java.time.Instant;

public record ExamSprintReport(
        String reportId,
        ExamSprintReportType reportType,
        JsonNode payload,
        ExamSprintReportGenerationStatus generationStatus,
        Instant createdAt,
        Instant updatedAt,
        Instant expiresAt,
        String storageObjectKey,
        String fileName,
        String failureReason) {

    public ExamSprintReport {
        payload = copyPayload(payload);
    }

    public static ExamSprintReport pending(
            String reportId,
            ExamSprintReportType reportType,
            JsonNode payload,
            Instant createdAt,
            Instant expiresAt) {
        return new ExamSprintReport(
                reportId,
                reportType,
                payload,
                ExamSprintReportGenerationStatus.PENDING,
                createdAt,
                createdAt,
                expiresAt,
                null,
                null,
                null);
    }

    public ExamSprintReport processing(Instant updatedAt) {
        return new ExamSprintReport(
                reportId,
                reportType,
                payload,
                ExamSprintReportGenerationStatus.PROCESSING,
                createdAt,
                updatedAt,
                expiresAt,
                storageObjectKey,
                fileName,
                null);
    }

    public ExamSprintReport success(Instant updatedAt, String storageObjectKey, String fileName) {
        return new ExamSprintReport(
                reportId,
                reportType,
                payload,
                ExamSprintReportGenerationStatus.SUCCESS,
                createdAt,
                updatedAt,
                expiresAt,
                storageObjectKey,
                fileName,
                null);
    }

    public ExamSprintReport failed(Instant updatedAt, String failureReason) {
        return new ExamSprintReport(
                reportId,
                reportType,
                payload,
                ExamSprintReportGenerationStatus.FAILED,
                createdAt,
                updatedAt,
                expiresAt,
                storageObjectKey,
                fileName,
                failureReason);
    }

    public ExamSprintReport expired(Instant updatedAt) {
        return new ExamSprintReport(
                reportId,
                reportType,
                payload,
                ExamSprintReportGenerationStatus.EXPIRED,
                createdAt,
                updatedAt,
                expiresAt,
                storageObjectKey,
                fileName,
                failureReason);
    }

    public ExamSprintReport expiredWithStorageCleared(Instant updatedAt) {
        return new ExamSprintReport(
                reportId,
                reportType,
                payload,
                ExamSprintReportGenerationStatus.EXPIRED,
                createdAt,
                updatedAt,
                expiresAt,
                null,
                null,
                failureReason);
    }

    public boolean isExpiredAt(Instant instant) {
        return !expiresAt.isAfter(instant);
    }

    @Override
    public JsonNode payload() {
        return copyPayload(payload);
    }

    private static JsonNode copyPayload(JsonNode payload) {
        return payload == null ? null : payload.deepCopy();
    }
}
