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

import cn.yunzhixue.ability.center.examsprint.contracts.report.ExamSprintReportType;
import cn.yunzhixue.ability.center.examsprint.domain.report.ExamSprintReportStorage;
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,
            ExamSprintReportType reportType,
            String fileName,
            byte[] pdfBytes,
            Instant expiresAt) {
        String typeSegment = reportType.name().toLowerCase();
        String storageObjectKey = "exam-sprint-reports/" + typeSegment + "/" + reportId + "/" + fileName;
        storage.put(storageObjectKey, new StoredFile(fileName, pdfBytes.clone(), "application/pdf"));
        return new StoredExamSprintReportFile(storageObjectKey, fileName);
    }

    @Override
    public URI generateDownloadUrl(String storageObjectKey, Duration ttl) {
        return URI.create("/api/exam-sprint/reports/" + reportId(storageObjectKey) + "/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 String reportId(String storageObjectKey) {
        String[] segments = storageObjectKey.split("/");
        return segments[2];
    }

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