package cn.yunzhixue.ability.center.examsprint.infrastructure.report.storage;

import cn.yunzhixue.ability.center.examsprint.domain.report.ExamSprintReportStorage;
import cn.yunzhixue.ability.center.examsprint.domain.report.ReportType;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ConditionalOnProperty(prefix = "ability.exam-sprint.report.storage", name = "type", havingValue = "memory", matchIfMissing = true)
public class InMemoryExamSprintReportStorage implements ExamSprintReportStorage {

    private final Map<String, StoredFile> storage = new ConcurrentHashMap<>();

    @Override
    public StoredExamSprintReportFile upload(
            String reportId,
            ReportType reportType,
            String fileName,
            byte[] pdfBytes,
            Instant expiresAt) {
        storage.put(fileName, new StoredFile(reportId, fileName, pdfBytes.clone(), "application/pdf"));
        return new StoredExamSprintReportFile(fileName, fileName);
    }

    @Override
    public URI generateDownloadUrl(String storageObjectKey, Duration ttl) {
        StoredFile storedFile = storage.get(storageObjectKey);
        if (storedFile == null) {
            throw new IllegalStateException("Unexpected storage object key: " + storageObjectKey);
        }
        return URI.create("/api/exam-sprint/reports/" + storedFile.reportId() + "/download");
    }

    @Override
    public Optional<StoredExamSprintReportContent> download(String storageObjectKey) {
        StoredFile storedFile = storage.get(storageObjectKey);
        if (storedFile == null) {
            return Optional.empty();
        }
        return Optional.of(new StoredExamSprintReportContent(
                storedFile.fileName(),
                storedFile.bytes().clone(),
                storedFile.contentType()));
    }

    @Override
    public void delete(String storageObjectKey) {
        storage.remove(storageObjectKey);
    }

    private record StoredFile(String reportId, String fileName, byte[] bytes, String contentType) {
    }
}
