package com.r35157.nenjim.service.journal.valuetypes;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
import java.util.Locale;
import java.util.Objects;

/** UTC publication time of a complete Journal worldview. */
public record JournalVersion(Instant instant) implements Comparable<JournalVersion> {
    private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
            .appendPattern("uuuuMMddHHmmssSSS")
            .appendLiteral('Z')
            .toFormatter(Locale.ROOT)
            .withResolverStyle(ResolverStyle.STRICT);

    public JournalVersion {
        Objects.requireNonNull(instant, "instant");
        if (instant.getNano() % 1_000_000 != 0) {
            throw new IllegalArgumentException("Journal version must have millisecond precision");
        }
    }

    public static JournalVersion parse(String value) {
        Objects.requireNonNull(value, "value");
        try {
            LocalDateTime timestamp = LocalDateTime.parse(value, FORMATTER);
            return new JournalVersion(timestamp.toInstant(ZoneOffset.UTC));
        } catch (DateTimeParseException exception) {
            throw new IllegalArgumentException(
                    "Expected UTC timestamp in uuuuMMddHHmmssSSS'Z' format: '" + value + "'", exception);
        }
    }

    @Override
    public int compareTo(JournalVersion other) {
        return instant.compareTo(Objects.requireNonNull(other, "other").instant);
    }

    @Override
    public String toString() {
        return FORMATTER.format(LocalDateTime.ofInstant(instant, ZoneOffset.UTC));
    }
}
