/**
 * セーブデータ (localStorage)。
 *
 * GameState はほぼ全てプレーンなデータだが、Rng インスタンスと
 * Uint8Array (powerCoverage) だけは特別扱いして復元する。
 */
import { Rng } from '../core/rng';
import type { GameState } from './state';

const SAVE_KEY = 'dcf-save-v1';
const SAVE_VERSION = 1;

export interface SaveMeta {
  day: number;
  money: number;
  rank: number;
  totalShipped: number;
  won: boolean;
  /** 保存日時 (epoch ms) */
  savedAt: number;
}

interface SaveFile {
  version: number;
  meta: SaveMeta;
  /** シリアライズした GameState。rng は数値、powerCoverage は配列に置き換えてある。 */
  state: Record<string, unknown>;
}

function safeStorage(): Storage | null {
  try {
    const test = '__dcf_probe__';
    window.localStorage.setItem(test, '1');
    window.localStorage.removeItem(test);
    return window.localStorage;
  } catch {
    return null;
  }
}

/** セーブデータが存在するか。 */
export function hasSave(): boolean {
  const storage = safeStorage();
  return storage !== null && storage.getItem(SAVE_KEY) !== null;
}

/** タイトル画面に出す要約だけを読む (本体は読み込まない)。 */
export function loadSaveMeta(): SaveMeta | null {
  const storage = safeStorage();
  if (!storage) return null;
  try {
    const raw = storage.getItem(SAVE_KEY);
    if (!raw) return null;
    const file = JSON.parse(raw) as SaveFile;
    return file.meta ?? null;
  } catch {
    return null;
  }
}

/** 現在の進行状況を保存する。 */
export function saveGame(s: GameState): boolean {
  const storage = safeStorage();
  if (!storage) return false;
  try {
    const clone: Record<string, unknown> = { ...s };
    clone.rng = s.rng.exportState();
    clone.powerCoverage = Array.from(s.powerCoverage);

    const file: SaveFile = {
      version: SAVE_VERSION,
      meta: {
        day: s.day,
        money: s.money,
        rank: s.rank,
        totalShipped: s.totalShipped,
        won: s.won,
        savedAt: Date.now(),
      },
      state: clone,
    };
    storage.setItem(SAVE_KEY, JSON.stringify(file));
    return true;
  } catch {
    return false;
  }
}

/** 保存されていた進行状況を復元する。壊れていれば null。 */
export function loadGame(): GameState | null {
  const storage = safeStorage();
  if (!storage) return null;
  try {
    const raw = storage.getItem(SAVE_KEY);
    if (!raw) return null;
    const file = JSON.parse(raw) as SaveFile;
    if (file.version !== SAVE_VERSION) return null;

    const data = file.state;
    data.rng = Rng.fromState(data.rng as number);
    data.powerCoverage = new Uint8Array((data.powerCoverage as number[]) ?? []);
    if (!data.routes) data.routes = [];
    // 古いセーブデータの猫にequipmentフィールドを補完
    if (Array.isArray(data.cats)) {
      for (const cat of data.cats as Record<string, unknown>[]) {
        if (!cat.equipment) cat.equipment = 'none';
      }
    }
    return data as unknown as GameState;
  } catch {
    return null;
  }
}

/** セーブデータを消す。 */
export function clearSave(): void {
  const storage = safeStorage();
  storage?.removeItem(SAVE_KEY);
}
