/* SportK — Store con persistencia en localStorage. v2 con migración desde v1. */

const STORAGE_KEY_V1 = "sportk_state_v1";
const STORAGE_KEY = "sportk_state_v2";

const defaultState = {
  profile: {
    audience: null, // female | male | all
    level: "beginner",
    track: "general-strength",
    goals: [], // ['strength','erection','ielt','edging','incontinence','postpartum','orgasmic']
    onboarded: false,
    locale: (window.detectBrowserLocale && window.detectBrowserLocale()) || "es",
    baseline: { holdMs: 0, flicksPer10s: 0, mvcSubjective: 5, takenAt: null },
    preferences: { soundOn: true, hapticOn: true, volume: 0.7, eyesClosedHint: true },
  },
  history: [], // [{date, routineId, routineName, track, totalReps, totalSets, durationSec, perExercise}]
  customRoutines: [],
  streak: 0,
  lastSessionDate: null,
  metrics: {
    monthlyTests: [], // [{date, holdMs, flicksPer10s, mvcSubjective}]
    ielt: [],         // [{date, seconds}]
    ehs: [],          // [{date, score}]  1..4
    conoG: [],        // [{date, grams}]
    rpe: [],          // [{date, rpe1to10}]
  },
  ui: {
    progressionDismissedAt: null, // evita spam del modal de subir nivel
  },
};

function migrateV1ToV2(v1) {
  // v1: { profile:{audience,level,onboarded}, history, customRoutines, streak, lastSessionDate }
  if (!v1) return null;
  const out = JSON.parse(JSON.stringify(defaultState));
  if (v1.profile) {
    out.profile.audience = v1.profile.audience || null;
    out.profile.level = v1.profile.level || "beginner";
    out.profile.onboarded = !!v1.profile.onboarded;
    // Asignar track por defecto según género (sin pedir al usuario):
    if (v1.profile.audience === "male") out.profile.track = "male-sexual";
    else if (v1.profile.audience === "female") out.profile.track = "female-postpartum-sexual";
    else out.profile.track = "general-strength";
  }
  out.history = (v1.history || []).map((h) => ({ ...h, track: h.track || "general-strength" }));
  // Filtrar custom routines y añadirles track default si falta
  out.customRoutines = (v1.customRoutines || []).map((r) => ({ ...r, track: r.track || "general-strength" }));
  out.streak = v1.streak || 0;
  out.lastSessionDate = v1.lastSessionDate || null;
  return out;
}

function deepMerge(base, patch) {
  if (!patch || typeof patch !== "object") return base;
  const out = Array.isArray(base) ? [...base] : { ...base };
  for (const k of Object.keys(patch)) {
    if (
      patch[k] && typeof patch[k] === "object" && !Array.isArray(patch[k]) &&
      base && typeof base[k] === "object" && !Array.isArray(base[k])
    ) {
      out[k] = deepMerge(base[k], patch[k]);
    } else {
      out[k] = patch[k];
    }
  }
  return out;
}

function loadState() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (raw) {
      const parsed = JSON.parse(raw);
      return deepMerge(defaultState, parsed);
    }
    // Intenta migrar de v1
    const rawV1 = localStorage.getItem(STORAGE_KEY_V1);
    if (rawV1) {
      const migrated = migrateV1ToV2(JSON.parse(rawV1));
      if (migrated) {
        try { localStorage.setItem(STORAGE_KEY, JSON.stringify(migrated)); } catch (e) {}
        return migrated;
      }
    }
    return defaultState;
  } catch (e) {
    return defaultState;
  }
}

function saveState(state) {
  try {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
  } catch (e) {}
}

function todayISO() {
  return new Date().toISOString();
}

function sameDay(aISO, bISO) {
  if (!aISO || !bISO) return false;
  return new Date(aISO).toDateString() === new Date(bISO).toDateString();
}

function isYesterday(aISO) {
  if (!aISO) return false;
  const y = new Date(Date.now() - 86400000).toDateString();
  return new Date(aISO).toDateString() === y;
}

function useStore() {
  const [state, setState] = React.useState(loadState);
  React.useEffect(() => {
    saveState(state);
  }, [state]);

  // Sincroniza preferencias con el módulo Feedback al cambiar.
  React.useEffect(() => {
    if (window.Feedback && state.profile.preferences) {
      window.Feedback.setPrefs({
        soundOn: state.profile.preferences.soundOn,
        hapticOn: state.profile.preferences.hapticOn,
        volume: state.profile.preferences.volume,
      });
    }
  }, [state.profile.preferences]);

  const updateProfile = (patch) =>
    setState((s) => ({ ...s, profile: { ...s.profile, ...patch } }));

  const updatePreferences = (patch) =>
    setState((s) => ({
      ...s,
      profile: {
        ...s.profile,
        preferences: { ...s.profile.preferences, ...patch },
      },
    }));

  const setBaseline = (baseline) =>
    setState((s) => ({
      ...s,
      profile: { ...s.profile, baseline: { ...s.profile.baseline, ...baseline, takenAt: todayISO() } },
    }));

  const addCustomRoutine = (routine) =>
    setState((s) => ({ ...s, customRoutines: [...s.customRoutines, routine] }));

  const deleteCustomRoutine = (id) =>
    setState((s) => ({ ...s, customRoutines: s.customRoutines.filter((r) => r.id !== id) }));

  const completeSession = (session) => {
    setState((s) => {
      const today = new Date().toDateString();
      const last = s.lastSessionDate ? new Date(s.lastSessionDate).toDateString() : null;
      const yesterday = new Date(Date.now() - 86400000).toDateString();
      let streak = s.streak;
      if (last === today) {
        // mismo día
      } else if (last === yesterday) {
        streak = streak + 1;
      } else {
        streak = 1;
      }
      return {
        ...s,
        history: [{ ...session, date: todayISO() }, ...s.history].slice(0, 120),
        streak,
        lastSessionDate: todayISO(),
      };
    });
  };

  const logTest = ({ holdMs, flicksPer10s, mvcSubjective }) => {
    setState((s) => ({
      ...s,
      metrics: {
        ...s.metrics,
        monthlyTests: [{ date: todayISO(), holdMs, flicksPer10s, mvcSubjective }, ...s.metrics.monthlyTests].slice(0, 36),
      },
      profile: {
        ...s.profile,
        baseline: {
          holdMs: holdMs ?? s.profile.baseline.holdMs,
          flicksPer10s: flicksPer10s ?? s.profile.baseline.flicksPer10s,
          mvcSubjective: mvcSubjective ?? s.profile.baseline.mvcSubjective,
          takenAt: todayISO(),
        },
      },
    }));
  };

  const logIELT = (seconds) => {
    setState((s) => ({
      ...s,
      metrics: { ...s.metrics, ielt: [{ date: todayISO(), seconds }, ...s.metrics.ielt].slice(0, 60) },
    }));
  };

  const logEHS = (score) => {
    setState((s) => ({
      ...s,
      metrics: { ...s.metrics, ehs: [{ date: todayISO(), score }, ...s.metrics.ehs].slice(0, 60) },
    }));
  };

  const logConoG = (grams) => {
    setState((s) => ({
      ...s,
      metrics: { ...s.metrics, conoG: [{ date: todayISO(), grams }, ...s.metrics.conoG].slice(0, 60) },
    }));
  };

  const dismissProgression = () =>
    setState((s) => ({ ...s, ui: { ...s.ui, progressionDismissedAt: todayISO() } }));

  const setLevel = (level) =>
    setState((s) => ({
      ...s,
      profile: { ...s.profile, level },
      ui: { ...s.ui, progressionDismissedAt: todayISO() },
    }));

  const reset = () => {
    setState(defaultState);
    try {
      localStorage.removeItem(STORAGE_KEY);
      localStorage.removeItem(STORAGE_KEY_V1);
    } catch (e) {}
  };

  // ---------- Cálculos derivados ----------

  // ¿Cumple los umbrales para subir de nivel?
  const progressionCheck = React.useMemo(() => {
    const lvl = state.profile.level;
    const next = window.nextLevelLabel ? window.nextLevelLabel(lvl) : null;
    if (!next) return { ready: false };
    const th = window.nextLevelThresholds ? window.nextLevelThresholds(lvl) : null;
    if (!th) return { ready: false };
    const baseline = state.profile.baseline || {};
    const baselineMet =
      (baseline.holdMs || 0) >= th.holdMs &&
      (baseline.flicksPer10s || 0) >= th.flicksPer10s;
    if (!baselineMet) return { ready: false, nextLevel: next, threshold: th };
    // Adherencia: 6 sesiones en últimos 14 días.
    const cutoff = Date.now() - 14 * 86400000;
    const recent = state.history.filter((h) => new Date(h.date).getTime() >= cutoff);
    if (recent.length < 6) return { ready: false, nextLevel: next, threshold: th, sessionsRecent: recent.length };
    // Ya descartado hoy?
    if (sameDay(state.ui.progressionDismissedAt, todayISO())) return { ready: false };
    return { ready: true, nextLevel: next, threshold: th };
  }, [state.profile.level, state.profile.baseline, state.history, state.ui.progressionDismissedAt]);

  return {
    state,
    updateProfile,
    updatePreferences,
    setBaseline,
    setLevel,
    addCustomRoutine,
    deleteCustomRoutine,
    completeSession,
    logTest,
    logIELT,
    logEHS,
    logConoG,
    dismissProgression,
    progressionCheck,
    reset,
  };
}

window.useStore = useStore;
