## EndlessRecords — 本地排行榜（Autoload: EndlessRecords）
## 权威来源：certification_checklist.md ST-40/41（HMAC-SHA256 防篡改）、P6-N19 评分公式
## 排名：到达波次为主、同波次按用时升序；在线分 = wave*100000 + (86400 - elapsed_sec)
extends Node

const RECORDS_PATH: String = "user://endless_records.json"
const MAX_RECORDS:  int = 50

## HMAC 密钥（不入存档；仅防普通玩家手改，无法对抗逆向，见 ST-40）
## PackedByteArray(...) 非常量表达式，故用 var 在加载时初始化
var _HMAC_KEY: PackedByteArray = PackedByteArray([
	0xA3, 0x7F, 0x2C, 0x91, 0x4E, 0xD8, 0x12, 0x6B,
	0xF0, 0x39, 0x5A, 0xCC, 0x77, 0x1D, 0x8E, 0x44,
	0x22, 0xB9, 0x60, 0x3F, 0xE1, 0x05, 0x9C, 0x7A,
	0x53, 0xD4, 0x08, 0x6F, 0xAB, 0x31, 0xC7, 0x90,
])

## P6-N19：单整数双维度评分（波次高优先；同波次剩余秒数高优先）
static func compute_score(wave: int, elapsed_sec: int) -> int:
	return wave * 100000 + (86400 - clampi(elapsed_sec, 0, 86400))

func _sign(data: String) -> String:
	var crypto := Crypto.new()
	var hmac := crypto.hmac_digest(HashingContext.HASH_SHA256, _HMAC_KEY, data.to_utf8_buffer())
	return hmac.hex_encode()

## 追加一条记录并持久化；返回排序后的全部记录
func add_record(wave: int, elapsed_sec: int, kills: int) -> Array:
	var records: Array = load_records()
	records.append({
		"wave":    wave,
		"elapsed": elapsed_sec,
		"kills":   kills,
		"score":   compute_score(wave, elapsed_sec),
	})
	records = _sort_records(records)
	if records.size() > MAX_RECORDS:
		records.resize(MAX_RECORDS)
	save_records(records)
	return records

## data 以 JSON 字符串存储并对该精确字符串签名（避免 JSON int↔float 往返破坏签名）
func save_records(records: Array) -> void:
	var payload: String = JSON.stringify(records)
	var signed: Dictionary = {"data": payload, "sig": _sign(payload)}
	var f := FileAccess.open(RECORDS_PATH, FileAccess.WRITE)
	if f:
		f.store_string(JSON.stringify(signed))
		f.close()

func load_records() -> Array:
	if not FileAccess.file_exists(RECORDS_PATH):
		return []
	var raw = JSON.parse_string(FileAccess.get_file_as_string(RECORDS_PATH))
	if not (raw is Dictionary):
		return []
	var payload: String = String(raw.get("data", ""))
	if _sign(payload) != String(raw.get("sig", "")):
		push_warning("EndlessRecords: 签名验证失败，分数不可信，拒绝载入")  # ST-41
		return []
	var data = JSON.parse_string(payload)
	return data if data is Array else []

## 波次降序、同波次用时升序（P6-N19）
func _sort_records(records: Array) -> Array:
	records.sort_custom(func(a, b):
		var wa: int = int(a.get("wave", 0))
		var wb: int = int(b.get("wave", 0))
		if wa != wb:
			return wa > wb
		return int(a.get("elapsed", 99999)) < int(b.get("elapsed", 99999)))
	return records

func get_top(n: int = 10) -> Array:
	var r: Array = load_records()
	return r.slice(0, min(n, r.size()))
