// BalkanBuddy — phrasebook app component
// Full-bleed, works at any size. Used inside iOS frames and standalone.

// ─── TTS via server proxy ────────────────────────────────────
// Speech comes from the /api/tts endpoint (same origin), which forwards
// to cloudlanguagetools-api.vocab.ai with a server-side API key.
// Azure Neural voices: it → Isabella, sq → Anila, mk → Marija, hr → Gabrijela.
// The browser never sees the key; it just plays the returned MP3.
//
// One shared <audio> element — starting a new play aborts the previous one.
const __bbAudio = typeof window !== 'undefined' ? new Audio() : null;
let __bbCurrentUrl = null;

function __bbStop() {
  if (!__bbAudio) return;
  __bbAudio.pause();
  __bbAudio.currentTime = 0;
  if (__bbCurrentUrl) { URL.revokeObjectURL(__bbCurrentUrl); __bbCurrentUrl = null; }
}

// Returns a Promise<{ok, reason?, status?, done}> — `done` is a Promise that
// resolves when playback ends or is cancelled.
async function SPEAK(text, langCode) {
  if (!__bbAudio) return { ok: false, reason: 'no-audio', done: Promise.resolve() };
  __bbStop();
  let res;
  try {
    res = await fetch('/api/tts', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ text, lang: langCode }),
    });
  } catch (e) {
    return { ok: false, reason: 'network', done: Promise.resolve() };
  }
  if (!res.ok) {
    const ct = res.headers.get('content-type') || '';
    let detail = '';
    try { detail = ct.includes('json') ? (await res.json()).error : await res.text(); } catch {}
    return { ok: false, reason: 'upstream', status: res.status, detail, done: Promise.resolve() };
  }
  const blob = await res.blob();
  const url = URL.createObjectURL(blob);
  __bbCurrentUrl = url;
  __bbAudio.src = url;
  const done = new Promise((resolve) => {
    const cleanup = () => {
      __bbAudio.removeEventListener('ended', cleanup);
      __bbAudio.removeEventListener('error', cleanup);
      __bbAudio.removeEventListener('pause', onPause);
      if (__bbCurrentUrl === url) { URL.revokeObjectURL(url); __bbCurrentUrl = null; }
      resolve();
    };
    const onPause = () => { if (__bbAudio.currentTime === 0) cleanup(); };
    __bbAudio.addEventListener('ended', cleanup);
    __bbAudio.addEventListener('error', cleanup);
    __bbAudio.addEventListener('pause', onPause);
  });
  try { await __bbAudio.play(); } catch (e) { return { ok: false, reason: 'play-blocked', done }; }
  return { ok: true, done };
}

// ─── Audio button with wave animation ─────────────────────────
function AudioButton({ text, langCode, size = 52, color = '#2B7A2B' }) {
  const [playing, setPlaying] = React.useState(false);
  const [loading, setLoading] = React.useState(false);
  const [warn, setWarn] = React.useState(null); // {reason, status?}
  const warnTimerRef = React.useRef(null);

  const play = async (e) => {
    e.stopPropagation();
    if (playing || loading) {
      __bbStop();
      setPlaying(false);
      setLoading(false);
      return;
    }
    setLoading(true);
    const res = await SPEAK(text, langCode);
    setLoading(false);
    if (!res.ok) {
      setWarn({ reason: res.reason, status: res.status });
      clearTimeout(warnTimerRef.current);
      warnTimerRef.current = setTimeout(() => setWarn(null), 4500);
      return;
    }
    setWarn(null);
    setPlaying(true);
    res.done.then(() => setPlaying(false));
  };

  const WarnBubble = () => {
    if (!warn) return null;
    const msg = warn.reason === 'network'
      ? 'Keine Verbindung zum TTS-Server'
      : warn.reason === 'upstream'
        ? (warn.status === 401 ? 'TTS-Kontingent / API-Key Problem' : `TTS-Server-Fehler (${warn.status || '?'})`)
        : warn.reason === 'play-blocked'
          ? 'Tippe nochmal — Audio wurde blockiert'
          : 'Audio nicht verfügbar';
    return (
      <div style={{
        position: 'absolute', bottom: 'calc(100% + 8px)', right: 0,
        background: '#2E2419', color: '#fff', padding: '6px 10px',
        borderRadius: 8, fontSize: 11, fontWeight: 700,
        whiteSpace: 'nowrap', pointerEvents: 'none', zIndex: 10,
        fontFamily: '"Nunito", system-ui',
        boxShadow: '0 4px 12px rgba(0,0,0,0.2)',
      }}>⚠ {msg}</div>
    );
  };

  return (
    <button
      onClick={play}
      style={{
        width: size, height: size, borderRadius: size / 2,
        background: color, border: 'none', cursor: 'pointer',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        boxShadow: `0 4px 0 ${shade(color, -18)}, 0 6px 14px rgba(0,0,0,0.12)`,
        position: 'relative', flexShrink: 0,
        transition: 'transform 80ms ease, box-shadow 80ms ease',
        transform: playing ? 'translateY(2px)' : 'translateY(0)',
        padding: 0,
      }}
      onMouseDown={e => e.currentTarget.style.transform = 'translateY(3px)'}
      onMouseUp={e => e.currentTarget.style.transform = playing ? 'translateY(2px)' : 'translateY(0)'}
      aria-label={playing ? 'Stop' : 'Play'}
    >
      <WarnBubble />
      {loading ? (
        // spinner ring
        <div style={{
          width: size * 0.42, height: size * 0.42,
          border: '3px solid rgba(255,255,255,0.25)',
          borderTopColor: '#fff', borderRadius: '50%',
          animation: 'bb-spin 0.7s linear infinite',
        }} />
      ) : playing ? (
        // equalizer
        <div style={{ display: 'flex', gap: 3, alignItems: 'center', height: 18 }}>
          {[0, 1, 2, 3].map(i => (
            <div key={i} style={{
              width: 3, background: '#fff', borderRadius: 2,
              animation: `bb-eq 0.7s ${i * 0.1}s ease-in-out infinite alternate`,
            }} />
          ))}
        </div>
      ) : (
        // speaker icon
        <svg width={size * 0.42} height={size * 0.42} viewBox="0 0 24 24" fill="none">
          <path d="M3 9v6h4l5 5V4L7 9H3z" fill="#fff"/>
          <path d="M16 8c1.5 1 2.5 2.5 2.5 4s-1 3-2.5 4" stroke="#fff" strokeWidth="2" strokeLinecap="round" fill="none"/>
          <path d="M19 5c2.5 1.5 4 4 4 7s-1.5 5.5-4 7" stroke="#fff" strokeWidth="2" strokeLinecap="round" fill="none" opacity="0.7"/>
        </svg>
      )}
    </button>
  );
}

function shade(hex, percent) {
  const n = parseInt(hex.replace('#', ''), 16);
  const r = Math.max(0, Math.min(255, (n >> 16) + percent * 2.55));
  const g = Math.max(0, Math.min(255, ((n >> 8) & 0xff) + percent * 2.55));
  const b = Math.max(0, Math.min(255, (n & 0xff) + percent * 2.55));
  return '#' + [r, g, b].map(x => Math.round(x).toString(16).padStart(2, '0')).join('');
}

// ─── Country header (swipeable) ──────────────────────────────
function CountryHeader({ index, onChange, countries, compact = false }) {
  const startX = React.useRef(null);
  const deltaX = React.useRef(0);
  const [drag, setDrag] = React.useState(0);

  const handleStart = (x) => { startX.current = x; deltaX.current = 0; };
  const handleMove = (x) => {
    if (startX.current == null) return;
    deltaX.current = x - startX.current;
    setDrag(deltaX.current);
  };
  const handleEnd = () => {
    if (startX.current == null) return;
    const d = deltaX.current;
    startX.current = null;
    setDrag(0);
    if (Math.abs(d) > 50) {
      const dir = d < 0 ? 1 : -1;
      const next = (index + dir + countries.length) % countries.length;
      onChange(next);
    }
  };

  const c = countries[index];
  const h = compact ? 140 : 180;

  return (
    <div
      onTouchStart={e => handleStart(e.touches[0].clientX)}
      onTouchMove={e => handleMove(e.touches[0].clientX)}
      onTouchEnd={handleEnd}
      onMouseDown={e => handleStart(e.clientX)}
      onMouseMove={e => startX.current != null && handleMove(e.clientX)}
      onMouseUp={handleEnd}
      onMouseLeave={handleEnd}
      style={{
        position: 'relative',
        background: `linear-gradient(135deg, ${c.colorA} 0%, ${c.colorB} 100%)`,
        padding: compact ? '20px 20px 24px' : '28px 24px 32px',
        color: '#fff',
        overflow: 'hidden',
        userSelect: 'none',
        cursor: 'grab',
        transition: 'background 400ms ease',
      }}
    >
      {/* decorative mountains */}
      <svg style={{ position: 'absolute', right: -20, bottom: -1, opacity: 0.25 }}
           width="220" height="110" viewBox="0 0 220 110">
        <path d="M0 110 L40 60 L70 80 L110 30 L150 70 L180 50 L220 90 L220 110 Z" fill="#fff"/>
      </svg>

      {/* sliding content */}
      <div style={{
        transform: `translateX(${drag}px)`,
        transition: startX.current == null ? 'transform 280ms cubic-bezier(.2,.8,.2,1)' : 'none',
        position: 'relative', zIndex: 1,
      }}>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 12, marginBottom: 6,
          fontSize: compact ? 13 : 14, fontWeight: 600,
          textTransform: 'uppercase', letterSpacing: 1.2, opacity: 0.9,
        }}>
          <span style={{ fontSize: compact ? 22 : 26 }}>{c.flag}</span>
          <span>{c.language}</span>
        </div>
        <div style={{
          fontSize: compact ? 32 : 40, fontWeight: 800, letterSpacing: -1,
          lineHeight: 1.05, marginBottom: 4,
          fontFamily: '"Nunito", "Baloo 2", system-ui, sans-serif',
        }}>{c.name}</div>
        <div style={{ fontSize: compact ? 13 : 15, opacity: 0.85, fontWeight: 500 }}>
          {c.tagline}
        </div>
      </div>

      {/* dots */}
      <div style={{
        display: 'flex', gap: 6, justifyContent: 'center',
        marginTop: compact ? 14 : 20, position: 'relative', zIndex: 1,
      }}>
        {countries.map((_, i) => (
          <button key={i} onClick={() => onChange(i)} style={{
            width: i === index ? 22 : 7, height: 7, borderRadius: 4,
            background: i === index ? '#fff' : 'rgba(255,255,255,0.45)',
            border: 'none', cursor: 'pointer', padding: 0,
            transition: 'all 200ms ease',
          }} />
        ))}
      </div>

      {/* swipe hint */}
      <div style={{
        position: 'absolute', top: compact ? 20 : 28, right: 20,
        fontSize: 11, opacity: 0.7, fontWeight: 600,
        display: 'flex', alignItems: 'center', gap: 4,
      }}>
        <span>WISCHEN</span>
        <svg width="14" height="10" viewBox="0 0 14 10" fill="none">
          <path d="M1 5h12M9 1l4 4-4 4" stroke="#fff" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
        </svg>
      </div>
    </div>
  );
}

// ─── Category pill row ───────────────────────────────────────
function CategoryPills({ active, onChange, categories }) {
  return (
    <div style={{
      display: 'flex', gap: 10, padding: '16px 20px',
      overflowX: 'auto', scrollbarWidth: 'none',
      background: '#FFFDF7',
      borderBottom: '1px solid #F0EADF',
    }}>
      <style>{`.bb-pills::-webkit-scrollbar { display: none; }`}</style>
      {categories.map(cat => {
        const on = active === cat.id;
        return (
          <button key={cat.id} onClick={() => onChange(cat.id)} style={{
            display: 'flex', alignItems: 'center', gap: 7,
            padding: '10px 16px', borderRadius: 20,
            background: on ? cat.fg : cat.bg,
            color: on ? '#fff' : cat.fg,
            border: 'none', cursor: 'pointer',
            fontFamily: '"Nunito", system-ui, sans-serif',
            fontWeight: 800, fontSize: 14, letterSpacing: -0.2,
            whiteSpace: 'nowrap', flexShrink: 0,
            boxShadow: on ? `0 3px 0 ${shade(cat.fg, -20)}` : 'none',
            transform: on ? 'translateY(-1px)' : 'none',
            transition: 'all 120ms ease',
          }}>
            <span style={{ fontSize: 18 }}>{cat.emoji}</span>
            <span>{cat.label}</span>
          </button>
        );
      })}
    </div>
  );
}

// ─── Phrase card ─────────────────────────────────────────────
function PhraseCard({ phrase, country, accent }) {
  const [expanded, setExpanded] = React.useState(false);

  return (
    <div
      onClick={() => setExpanded(!expanded)}
      style={{
        background: '#fff', borderRadius: 20, padding: 18,
        marginBottom: 12, cursor: 'pointer',
        boxShadow: '0 2px 0 #E8DFCD, 0 4px 16px rgba(0,0,0,0.04)',
        border: '2px solid #F0EADF',
        transition: 'all 160ms ease',
      }}
    >
      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 14 }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          {/* German hint */}
          <div style={{
            fontSize: 12, fontWeight: 700, color: '#9B8F78',
            textTransform: 'uppercase', letterSpacing: 0.8,
            marginBottom: 4, fontFamily: '"Nunito", system-ui',
          }}>
            {phrase.de}
          </div>
          {/* Original (big) */}
          <div style={{
            fontSize: 22, fontWeight: 800, color: '#2E2419',
            lineHeight: 1.2, letterSpacing: -0.4,
            fontFamily: '"Nunito", "Baloo 2", system-ui',
            textWrap: 'pretty',
          }}>
            {phrase.orig}
          </div>
          {/* Pronunciation hint */}
          <div style={{
            fontSize: 13, color: accent, marginTop: 6,
            fontFamily: '"JetBrains Mono", "SF Mono", Menlo, monospace',
            fontWeight: 500,
          }}>
            [{phrase.ausspr}]
          </div>
        </div>
        <AudioButton text={phrase.orig} langCode={country.langCode} color={accent} />
      </div>

      {/* Context */}
      <div style={{
        marginTop: expanded ? 14 : 10,
        padding: expanded ? '12px 14px' : '8px 12px',
        background: '#FFF8E8',
        borderRadius: 12,
        fontSize: 13, lineHeight: 1.45,
        color: '#6B5A3A', fontWeight: 500,
        display: 'flex', gap: 8, alignItems: 'flex-start',
        fontFamily: '"Nunito", system-ui',
        maxHeight: expanded ? 200 : 40,
        overflow: 'hidden',
        transition: 'all 200ms ease',
      }}>
        <span style={{ fontSize: 14, flexShrink: 0 }}>💡</span>
        <span style={{
          display: '-webkit-box',
          WebkitLineClamp: expanded ? 99 : 1,
          WebkitBoxOrient: 'vertical',
          overflow: 'hidden',
        }}>{phrase.context}</span>
      </div>
    </div>
  );
}

// ─── Full app ────────────────────────────────────────────────
function BalkanBuddy({ initialCountry = 0, initialCat = 'greet', compact = false, showBrand = true }) {
  const [countryIdx, setCountryIdx] = React.useState(initialCountry);
  const [cat, setCat] = React.useState(initialCat);
  const country = COUNTRIES[countryIdx];
  const phrases = VOCAB[country.id][cat] || [];
  const category = CATEGORIES.find(c => c.id === cat);

  return (
    <div style={{
      height: '100%', display: 'flex', flexDirection: 'column',
      background: '#FFFDF7', fontFamily: '"Nunito", system-ui, sans-serif',
    }}>
      {showBrand && (
        <div style={{
          padding: '14px 20px 10px',
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          background: '#FFFDF7',
        }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <div style={{
              width: 32, height: 32, borderRadius: 10,
              background: 'linear-gradient(135deg, #FFB800, #FF6B35)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontSize: 18, boxShadow: '0 2px 0 #C74F17',
            }}>🦉</div>
            <div style={{
              fontSize: 17, fontWeight: 900, color: '#2E2419',
              letterSpacing: -0.5,
            }}>Balkan<span style={{color:'#FF6B35'}}>Buddy</span></div>
          </div>
          <div style={{
            fontSize: 12, fontWeight: 700, color: '#9B8F78',
            padding: '4px 10px', borderRadius: 20, background: '#F5EDD9',
          }}>
            {COUNTRIES.length} Länder
          </div>
        </div>
      )}

      <CountryHeader
        index={countryIdx}
        onChange={setCountryIdx}
        countries={COUNTRIES}
        compact={compact}
      />

      <CategoryPills active={cat} onChange={setCat} categories={CATEGORIES} />

      {/* Phrases */}
      <div style={{ flex: 1, overflow: 'auto', padding: '16px 16px 80px', background: '#FAF6EC' }}>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 8,
          marginBottom: 12, padding: '0 4px',
        }}>
          <span style={{ fontSize: 18 }}>{category.emoji}</span>
          <span style={{
            fontSize: 15, fontWeight: 800, color: '#2E2419',
            letterSpacing: -0.3,
          }}>{category.label}</span>
          <span style={{
            fontSize: 12, color: '#9B8F78', fontWeight: 700,
            marginLeft: 'auto',
          }}>{cat === 'info' ? '' : `${phrases.length} Phrasen`}</span>
        </div>

        {cat === 'info' ? (
          <LanguageInfo country={country} />
        ) : (
          <>
            {phrases.map((p, i) => (
              <PhraseCard key={`${country.id}-${cat}-${i}`} phrase={p} country={country} accent={category.fg} />
            ))}
            <div style={{
              textAlign: 'center', padding: '20px 20px 10px',
              fontSize: 12, color: '#B5A890', fontWeight: 600,
            }}>
              Tippe eine Karte für mehr Kontext · 🔊 für Aussprache
            </div>
          </>
        )}
      </div>
    </div>
  );
}

// ─── Sprach-Info-Ansicht ────────────────────────────────────
// Eingesetzt, wenn Kategorie "info" gewählt ist. Zeigt Sprachprofil:
// Sprachfamilie, Sprecher, Schrift, Aussprache-Tipps, Essentials + Audio.
function LanguageInfo({ country }) {
  const info = LANGUAGE_INFO[country.langCode];
  if (!info) {
    return (
      <div style={{ padding: 40, textAlign: 'center', color: '#9B8F78' }}>
        Für diese Sprache liegt kein Profil vor.
      </div>
    );
  }
  const accent = country.colorAccent || country.colorB || '#2E2419';
  const labelChip = (label) => (
    <span style={{
      fontSize: 11, fontWeight: 800, color: '#9B8F78',
      textTransform: 'uppercase', letterSpacing: 1,
      marginBottom: 4, display: 'block',
    }}>{label}</span>
  );
  const card = (children, extra = {}) => (
    <div style={{
      background: '#fff', borderRadius: 16, padding: 18, marginBottom: 12,
      boxShadow: '0 2px 8px rgba(0,0,0,0.04)', border: '1px solid #F0EADF',
      ...extra,
    }}>{children}</div>
  );

  return (
    <div style={{ paddingBottom: 20 }}>
      {/* Hero */}
      <div style={{
        background: `linear-gradient(135deg, ${country.colorA} 0%, ${country.colorB} 100%)`,
        borderRadius: 18, padding: '22px 20px', color: '#fff',
        marginBottom: 16, position: 'relative', overflow: 'hidden',
      }}>
        <div style={{ fontSize: 12, fontWeight: 800, textTransform: 'uppercase', letterSpacing: 1.4, opacity: 0.85 }}>
          {info.nativeName}
        </div>
        <div style={{
          fontSize: 32, fontWeight: 900, letterSpacing: -1, lineHeight: 1.1,
          fontFamily: '"Baloo 2", system-ui', marginTop: 2,
        }}>
          {info.name}
        </div>
        <div style={{ fontSize: 14, fontWeight: 500, opacity: 0.92, marginTop: 6 }}>
          {info.family}
        </div>
      </div>

      {/* Facts grid */}
      {card(
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
          <div>
            {labelChip('Sprecher')}
            <div style={{ fontSize: 15, fontWeight: 700, color: '#2E2419' }}>{info.speakers}</div>
          </div>
          <div>
            {labelChip('Schrift')}
            <div style={{ fontSize: 15, fontWeight: 700, color: '#2E2419' }}>{info.script}</div>
          </div>
          <div style={{ gridColumn: '1 / -1' }}>
            {labelChip('Gesprochen in')}
            <div style={{ fontSize: 14, fontWeight: 600, color: '#2E2419', lineHeight: 1.4 }}>{info.countries}</div>
          </div>
        </div>
      )}

      {/* Essentials with audio */}
      {card(
        <>
          {labelChip('Erste Wörter')}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 6 }}>
            {info.essentials.map((e, i) => (
              <div key={i} style={{
                display: 'flex', alignItems: 'center', gap: 12,
                padding: '10px 4px', borderBottom: i < info.essentials.length - 1 ? '1px solid #F6F0E4' : 'none',
              }}>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 12, color: '#9B8F78', fontWeight: 700, marginBottom: 2 }}>{e.label}</div>
                  <div style={{ fontSize: 16, fontWeight: 800, color: '#2E2419', letterSpacing: -0.3 }}>{e.value}</div>
                </div>
                <AudioButton
                  text={e.value.replace(/\s*\(.*?\)\s*/g, '').replace(/\s*\/\s*/g, ', ')}
                  langCode={country.langCode}
                  size={40}
                  color={accent}
                />
              </div>
            ))}
          </div>
        </>
      )}

      {/* Pronunciation tips */}
      {card(
        <>
          {labelChip('Aussprache-Tipps')}
          <ul style={{
            margin: '6px 0 0', paddingLeft: 18,
            fontSize: 14, color: '#2E2419', lineHeight: 1.55, fontWeight: 500,
          }}>
            {info.pronunciation.map((p, i) => <li key={i} style={{ marginBottom: 4 }}>{p}</li>)}
          </ul>
        </>
      )}

      {/* Fun fact */}
      {card(
        <>
          {labelChip('Gut zu wissen')}
          <div style={{ fontSize: 14, color: '#2E2419', lineHeight: 1.55, fontWeight: 500, marginTop: 4 }}>
            {info.fact}
          </div>
        </>,
        { background: '#FFF9E8', borderColor: '#F3E5B8' }
      )}

      {/* Travel tip */}
      {info.tip && card(
        <>
          {labelChip('Reisetipp')}
          <div style={{ fontSize: 14, color: '#2E2419', lineHeight: 1.55, fontWeight: 500, marginTop: 4 }}>
            💡 {info.tip}
          </div>
        </>,
        { background: '#E8F5EC', borderColor: '#CDE8D4' }
      )}
    </div>
  );
}

Object.assign(window, { BalkanBuddy, AudioButton, CountryHeader, CategoryPills, PhraseCard, LanguageInfo });
