// profile.jsx
// Single source of truth for in-browser kid state.
// Stored under m4k-profile in localStorage. No personal data leaves the device.
//
// Migrates the legacy m4k-stickers key on first load so existing kids keep their progress.

const PROFILE_KEY = 'm4k-profile';
const LEGACY_STICKERS_KEY = 'm4k-stickers';

function defaultProfile() {
  return {
    version: 1,
    age: null,
    createdAt: Date.now(),
    perGame: {},          // { [gameId]: { difficulty: number, recentResults: [] } }
    stickers: [],
    wonCodes: [],
    redeemedCodes: [],
  };
}

function readProfile() {
  let parsed = null;
  try {
    const raw = localStorage.getItem(PROFILE_KEY);
    if (raw) parsed = JSON.parse(raw);
  } catch (_) {
    parsed = null;
  }
  if (!parsed || typeof parsed !== 'object') {
    parsed = defaultProfile();
    // One-time migration: pull stickers out of the old key if present.
    try {
      const legacyRaw = localStorage.getItem(LEGACY_STICKERS_KEY);
      if (legacyRaw) {
        const legacy = JSON.parse(legacyRaw);
        if (Array.isArray(legacy)) parsed.stickers = legacy.filter(s => typeof s === 'string');
      }
    } catch (_) { /* ignore */ }
  }
  // Defensive defaults so older saved profiles do not break new code paths.
  return { ...defaultProfile(), ...parsed };
}

function writeProfile(p) {
  try {
    localStorage.setItem(PROFILE_KEY, JSON.stringify(p));
  } catch (_) {
    // Quota or private mode: silently fail. State stays in memory for this session.
  }
}

// Hook: returns [profile, updateProfile] where updateProfile takes either
// a partial object or an updater function. Persists on every change.
function useProfile() {
  const [profile, setProfile] = React.useState(readProfile);

  React.useEffect(() => { writeProfile(profile); }, [profile]);

  const updateProfile = React.useCallback((edits) => {
    setProfile((prev) => {
      const next = typeof edits === 'function' ? edits(prev) : { ...prev, ...edits };
      return next;
    });
  }, []);

  return [profile, updateProfile];
}

// Append a single round result to the recent history of a game, keeping
// only the last 5 entries so adaptive.jsx has a fixed window to inspect.
function appendResult(profile, gameId, result) {
  const slot = profile.perGame[gameId] || { difficulty: 0.3, recentResults: [] };
  const recentResults = [...slot.recentResults, result].slice(-5);
  return {
    ...profile,
    perGame: { ...profile.perGame, [gameId]: { ...slot, recentResults } },
  };
}

function setGameDifficulty(profile, gameId, difficulty) {
  const slot = profile.perGame[gameId] || { difficulty, recentResults: [] };
  return {
    ...profile,
    perGame: { ...profile.perGame, [gameId]: { ...slot, difficulty } },
  };
}

function addSticker(profile, sticker) {
  if (profile.stickers.includes(sticker)) return profile;
  return { ...profile, stickers: [...profile.stickers, sticker] };
}

function addWonCode(profile, code) {
  if (profile.wonCodes.includes(code)) return profile;
  return { ...profile, wonCodes: [...profile.wonCodes, code] };
}

function addRedeemedCode(profile, code) {
  if (profile.redeemedCodes.includes(code)) return profile;
  return { ...profile, redeemedCodes: [...profile.redeemedCodes, code] };
}

Object.assign(window, {
  useProfile,
  appendResult,
  setGameDifficulty,
  addSticker,
  addWonCode,
  addRedeemedCode,
  defaultProfile,
});
