package dev.photosync.core.upload;

import dev.photosync.core.capture.CaptureOrigin;
import dev.photosync.core.provider.AlbumRef;
import dev.photosync.core.provider.UploadRequest;
import lombok.Builder;

import java.nio.file.Path;
import java.time.Instant;
import java.util.Optional;

/**
 * One screenshot's journey to the backend, as an immutable value.
 *
 * <p>Every transition produces a new job rather than mutating one, so the queue
 * can hand a consistent snapshot to the GUI while workers are running, without
 * copying or locking on the render thread.
 *
 * <p>The file is held as a string rather than a {@link Path} because this record
 * is serialized straight to the queue file, and Gson has no idea what to do with
 * a filesystem-specific {@code Path} implementation.
 */
@Builder(toBuilder = true)
public record UploadJob(
        String id,
        String file,
        String fileName,
        long sizeBytes,
        Instant capturedAt,
        CaptureOrigin origin,
        String albumId,
        String description,
        UploadState state,
        int attempts,
        Instant notBefore,
        String lastError,
        String assetId) {

    public Path path() {
        return Path.of(file);
    }

    public AlbumRef album() {
        return AlbumRef.of(albumId);
    }

    public Optional<String> failureMessage() {
        return Optional.ofNullable(lastError).filter(message -> !message.isBlank());
    }

    public UploadRequest toRequest() {
        return new UploadRequest(path(), fileName, capturedAt, capturedAt, album(), description);
    }

    /** True once the backoff has elapsed and a worker may pick this up. */
    public boolean isClaimable(Instant now) {
        return switch (state) {
            case PENDING -> true;
            case RETRYING -> notBefore == null || !notBefore.isAfter(now);
            default -> false;
        };
    }
}
