/* SportK — Capa de feedback multisensorial (audio + háptica)
   Sin dependencias externas. Usa Web Audio API y navigator.vibrate.
   El AudioContext se inicializa lazily tras la primera interacción del usuario
   (políticas iOS Safari).
*/

const Feedback = (() => {
  let ctx = null;
  let masterGain = null;
  let prefs = {
    soundOn: true,
    hapticOn: true,
    volume: 0.7, // 0..1
  };

  function ensureCtx() {
    if (ctx) return ctx;
    try {
      const AC = window.AudioContext || window.webkitAudioContext;
      if (!AC) return null;
      ctx = new AC();
      masterGain = ctx.createGain();
      masterGain.gain.value = prefs.volume;
      masterGain.connect(ctx.destination);
    } catch (e) {
      ctx = null;
    }
    return ctx;
  }

  function setPrefs(p) {
    prefs = { ...prefs, ...p };
    if (masterGain) masterGain.gain.value = prefs.volume;
  }

  function getPrefs() {
    return { ...prefs };
  }

  // Tono ADSR mini
  function tone({ freq = 440, ms = 80, type = "sine", attack = 0.005, release = 0.05, gain = 1 }) {
    if (!prefs.soundOn) return;
    const c = ensureCtx();
    if (!c) return;
    if (c.state === "suspended") c.resume();
    const t0 = c.currentTime;
    const osc = c.createOscillator();
    const env = c.createGain();
    osc.type = type;
    osc.frequency.value = freq;
    env.gain.setValueAtTime(0, t0);
    env.gain.linearRampToValueAtTime(gain, t0 + attack);
    env.gain.setValueAtTime(gain, t0 + Math.max(0, ms / 1000 - release));
    env.gain.linearRampToValueAtTime(0, t0 + ms / 1000);
    osc.connect(env);
    env.connect(masterGain);
    osc.start(t0);
    osc.stop(t0 + ms / 1000 + 0.02);
  }

  function chord(freqs, ms, type = "sine", gain = 0.7) {
    freqs.forEach((f) => tone({ freq: f, ms, type, gain }));
  }

  // Patrones de háptica
  const HAPTIC = {
    light: 18,
    medium: 36,
    strong: [70, 30, 70],
    flick: [30, 50, 30],
    success: [20, 40, 20, 40, 60],
    warn: [120, 60, 120],
    soft: 12,
  };

  function vibrate(pattern) {
    if (!prefs.hapticOn) return;
    if (typeof navigator === "undefined" || !navigator.vibrate) return;
    try {
      navigator.vibrate(pattern);
    } catch (e) {}
  }

  // ---- API de alto nivel: cuePhase ----
  // Mapea fase del engine → tono + vibración.
  function cuePhase(phase, info = {}) {
    switch (phase) {
      case "ready":
        tone({ freq: 440, ms: 60, type: "sine", gain: 0.5 });
        vibrate(HAPTIC.soft);
        break;
      case "inhale":
        // tono pad bajo, suave
        tone({ freq: 261, ms: 220, type: "sine", attack: 0.04, release: 0.18, gain: 0.4 });
        vibrate(HAPTIC.soft);
        break;
      case "exhale":
        tone({ freq: 196, ms: 220, type: "sine", attack: 0.04, release: 0.18, gain: 0.35 });
        break;
      case "contract":
        // beep nítido + vibración media
        tone({ freq: 660, ms: 70, type: "triangle", gain: 0.7 });
        vibrate(HAPTIC.medium);
        break;
      case "hold":
      case "knack-hold":
        // marca inicio de mantenimiento
        chord([523, 784], 90, "sine", 0.45);
        vibrate(HAPTIC.light);
        break;
      case "release":
        tone({ freq: 392, ms: 140, type: "sine", attack: 0.01, release: 0.12, gain: 0.5 });
        vibrate(HAPTIC.light);
        break;
      case "rest":
        tone({ freq: 330, ms: 90, type: "sine", gain: 0.45 });
        break;
      case "reverse":
        // tono bajo distinto: empuje suave, ámbar/violeta
        tone({ freq: 294, ms: 180, type: "sine", attack: 0.03, release: 0.14, gain: 0.5 });
        vibrate(HAPTIC.soft);
        break;
      case "peak":
        chord([660, 880], 90, "triangle", 0.55);
        vibrate(HAPTIC.medium);
        break;
      case "plateau":
        tone({ freq: 523, ms: 60, type: "sine", gain: 0.4 });
        vibrate(HAPTIC.light);
        break;
      case "knack-trigger":
        // simulación de "tos" para entrenar contracción anticipatoria
        tone({ freq: 180, ms: 110, type: "sawtooth", gain: 0.6 });
        setTimeout(() => tone({ freq: 140, ms: 90, type: "sawtooth", gain: 0.5 }), 90);
        vibrate(HAPTIC.warn);
        break;
      case "session-complete":
        chord([523, 659, 784], 120, "sine", 0.6);
        setTimeout(() => chord([659, 784, 1046], 180, "sine", 0.6), 140);
        vibrate(HAPTIC.success);
        break;
      case "tick":
        // tick suave en cada segundo de hold
        tone({ freq: 220, ms: 25, type: "sine", gain: 0.18 });
        break;
      case "arousal-tick":
        // Pulso cálido cada segundo durante la fase 'arousal' (Stop-Start).
        // Acorde de quinta justa (D5 + A5) — recordatorio sensorial sin alarmar.
        chord([587, 880], 70, "sine", 0.32);
        vibrate(HAPTIC.soft);
        break;
      case "countdown":
        tone({ freq: info.last ? 880 : 660, ms: 60, type: "sine", gain: 0.55 });
        vibrate(HAPTIC.light);
        break;
      default:
        break;
    }
  }

  function playCountdown(n = 3) {
    for (let i = 0; i < n; i++) {
      setTimeout(() => cuePhase("countdown", { last: i === n - 1 }), i * 1000);
    }
  }

  function unlock() {
    // Llamar tras un tap para que iOS habilite el AudioContext.
    const c = ensureCtx();
    if (c && c.state === "suspended") c.resume();
  }

  function supportsHaptic() {
    return typeof navigator !== "undefined" && !!navigator.vibrate;
  }

  return {
    cuePhase,
    playCountdown,
    tone,
    vibrate,
    setPrefs,
    getPrefs,
    unlock,
    supportsHaptic,
    HAPTIC,
  };
})();

window.Feedback = Feedback;
