import type { SaveData } from "../types/save.js";
import { SAVE_FORMAT_VERSION } from "../types/save.js";
import { isRecord, isVec3, type ValidationResult } from "./common.js";

export function validateSaveData(input: unknown): ValidationResult<SaveData> {
  const errors: string[] = [];

  if (!isRecord(input)) return { ok: false, errors: ["save must be an object"] };

  if (input["version"] !== SAVE_FORMAT_VERSION) {
    errors.push(
      `unsupported save version ${String(input["version"])}, expected ${SAVE_FORMAT_VERSION}`,
    );
  }
  if (typeof input["campaign"] !== "string") errors.push("campaign must be a string");
  if (typeof input["playtimeSeconds"] !== "number") errors.push("playtimeSeconds must be a number");
  if (!Array.isArray(input["flags"])) errors.push("flags must be an array");
  if (!Array.isArray(input["consumedInteractables"])) {
    errors.push("consumedInteractables must be an array");
  }

  const player = input["player"];
  if (!isRecord(player)) {
    errors.push("player must be an object");
  } else {
    if (typeof player["roomId"] !== "string") errors.push("player.roomId must be a string");
    if (!isVec3(player["position"])) errors.push("player.position must be a Vec3");
    if (typeof player["yaw"] !== "number") errors.push("player.yaw must be a number");
    if (typeof player["health"] !== "number") errors.push("player.health must be a number");
    const inventory = player["inventory"];
    if (
      !isRecord(inventory) ||
      !Array.isArray(inventory["slots"]) ||
      typeof inventory["capacity"] !== "number"
    ) {
      errors.push("player.inventory must have slots[] and capacity");
    }
  }

  return errors.length === 0
    ? { ok: true, value: input as unknown as SaveData }
    : { ok: false, errors };
}
