package com.lingniu.ingest.api.event;

import com.lingniu.ingest.api.ProtocolId;

import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Map;

/**
 * Shared raw-archive key conventions used by Dispatcher, archive sink, and query services.
 *
 * <p>32960 生产链路里，RAW .bin 文件本体按 {@code 日期/协议/VIN/eventId.bin} 落在 archive 根目录，
 * TDengine raw_frames 或兼容索引只保存 {@code archive://...} 引用。这个类集中维护 key 规则，
 * 避免接收端、落盘端、snapshot 查询端对目录分区的理解不一致。</p>
 */
public final class RawArchiveKeys {

    public static final String META_EVENT_ID = "rawArchiveEventId";
    public static final String META_KEY = "rawArchiveKey";
    public static final String META_URI = "rawArchiveUri";
    public static final String META_PARSED_JSON = "rawArchiveParsedJson";

    private static final DateTimeFormatter DATE_KEY =
            DateTimeFormatter.ofPattern("yyyy/MM/dd").withZone(ZoneId.of("Asia/Shanghai"));

    private RawArchiveKeys() {
    }

    public static String key(Instant ingestTime, ProtocolId source, String vin, String eventId) {
        // 分区日期使用 ingestTime 的东八区自然日，和磁盘目录保持一致；eventTime 只代表车端上报时间。
        String dateKey = DATE_KEY.format(ingestTime == null ? Instant.EPOCH : ingestTime);
        String safeVin = vin == null || vin.isBlank() ? "unknown-vin" : vin;
        String safeEventId = eventId == null || eventId.isBlank()
                ? Long.toHexString(System.nanoTime()) : eventId;
        String safeSource = source == null ? "UNKNOWN" : source.name();
        return dateKey + "/" + safeSource + "/" + safeVin + "/" + safeEventId + ".bin";
    }

    public static String key(VehicleEvent.RawArchive raw) {
        String key = metadataValue(raw.metadata(), META_KEY);
        if (!key.isBlank()) {
            return key;
        }
        return key(raw.ingestTime(), raw.source(), raw.vin(), raw.eventId());
    }

    public static String logicalUri(String key) {
        return key == null || key.isBlank() ? "" : "archive://" + key;
    }

    private static String metadataValue(Map<String, String> metadata, String key) {
        if (metadata == null || key == null) {
            return "";
        }
        String value = metadata.get(key);
        return value == null ? "" : value;
    }
}
