// Shared components: Card, Navigation, Divider, Phase rail, etc.

const { useState, useEffect, useRef, useCallback } = React;

// ────────────────────────────────────────────────────────────────
// Tarot Card
// ────────────────────────────────────────────────────────────────
function TarotCard({ card, flipped = false, reversed = false, size = '', interactive = false, onClick, style, className = '' }) {
  const sizeCls = size === 'lg' ? 'lg' : size === 'sm' ? 'sm' : size === 'xs' ? 'xs' : '';
  // If we have a painted illustration for this card, render that instead of the procedural sigil layout.
  const hasArt = !!(card && card.id);
  const showOrnaments = !hasArt && (size === 'lg' || size === '');
  const pipName = card && card.suitKey !== 'major' ? `pip-${card.suitKey}` : null;
  return (
    <div
      className={`card ${sizeCls} ${flipped ? 'flipped' : ''} ${reversed ? 'reversed' : ''} ${interactive ? 'interactive' : ''} ${card ? 'suit-' + (card.suitKey || 'major') : ''} ${hasArt ? 'has-art' : ''} ${className}`}
      style={style}
      onClick={onClick}
      role={interactive ? 'button' : undefined}
    >
      <div className="card-inner">
        <div className="card-face card-back">
          <div className="card-back-ornament">
            <Ornament name="back-ornament"/>
          </div>
        </div>
        {card && (
          <div className="card-face card-front">
            {hasArt ? (
              <img className="card-art" src={`assets/cards/${card.id}.png`} alt={card.name} draggable="false"/>
            ) : (
              <>
                {showOrnaments && (
                  <>
                    <span className="card-corner-orn tl"><Ornament name="corner-filigree"/></span>
                    <span className="card-corner-orn tr"><Ornament name="corner-filigree"/></span>
                    <span className="card-corner-orn bl"><Ornament name="corner-filigree"/></span>
                    <span className="card-corner-orn br"><Ornament name="corner-filigree"/></span>
                  </>
                )}
                <div className="card-front-inner">
                  {showOrnaments && pipName && (
                    <div className="card-pips top">
                      <Ornament name={pipName}/>
                      <Ornament name={pipName}/>
                    </div>
                  )}
                  <div className="card-numeral-row">
                    {showOrnaments && <span className="card-side-orn"></span>}
                    <div className="card-numeral">{card.roman}</div>
                    {showOrnaments && <span className="card-side-orn"></span>}
                  </div>
                  <div className="card-sigil-wrap">
                    {showOrnaments && (
                      <div className="card-mandala">
                        <Ornament name="mandala"/>
                      </div>
                    )}
                    <div className="card-sigil"><Sigil name={card.sigil}/></div>
                  </div>
                  <div className="card-name-block">
                    {showOrnaments && (
                      <div className="card-name-divider">
                        <Ornament name="crown-divider"/>
                      </div>
                    )}
                    <div className="card-name">{card.suitKey === 'major' ? card.name : card.shortName}</div>
                    {card.suitKey !== 'major' && <div className="card-suit">of {card.suit}</div>}
                  </div>
                  {showOrnaments && pipName && (
                    <div className="card-pips bottom">
                      <Ornament name={pipName}/>
                      <Ornament name={pipName}/>
                    </div>
                  )}
                </div>
              </>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────
// Divider with central glyph
// ────────────────────────────────────────────────────────────────
function Divider({ glyph = 'mark' }) {
  return (
    <div className="divider">
      <Sigil name={glyph}/>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────
// Frame corners
// ────────────────────────────────────────────────────────────────
function PanelCorners() {
  return (
    <>
      <span className="panel-corner tl"></span>
      <span className="panel-corner tr"></span>
      <span className="panel-corner bl"></span>
      <span className="panel-corner br"></span>
    </>
  );
}

// ────────────────────────────────────────────────────────────────
// Navigation
// ────────────────────────────────────────────────────────────────
function Nav({ route, onRoute, soundOn, onSoundToggle, onOpenSettings }) {
  const links = [
    { id: 'spreads',  label: 'Reading' },
    { id: 'library',  label: 'The Cards' },
    { id: 'journal',  label: 'Journal' },
    { id: 'about',    label: 'About' },
  ];
  return (
    <nav className="nav">
      <div className="nav-brand" onClick={() => onRoute('home')}>
        <Sigil name="mark"/>
        <span>Veiled · Tarot</span>
      </div>
      <div className="nav-links">
        {links.map(l => (
          <a key={l.id}
             className={`nav-link ${route === l.id || (l.id === 'spreads' && route === 'reading') ? 'active' : ''}`}
             onClick={() => onRoute(l.id)}>
            {l.label}
          </a>
        ))}
      </div>
      <div className="nav-utility">
        <button className="nav-icon-btn" onClick={onSoundToggle} title={soundOn ? 'Mute ambience' : 'Play ambience'}>
          <Sigil name={soundOn ? 'volume' : 'volume-off'}/>
          <span>{soundOn ? 'Ambience' : 'Silent'}</span>
        </button>
        <button className="nav-icon-btn" onClick={onOpenSettings} title="Voice settings">
          <Sigil name="sigil-mark"/>
          <span>Voice</span>
        </button>
      </div>
    </nav>
  );
}

// ────────────────────────────────────────────────────────────────
// Settings panel — ElevenLabs API key
// ────────────────────────────────────────────────────────────────
function SettingsPanel({ open, onClose, user }) {
  const [key, setKey] = useState(() => TTS.getElevenKey());
  const [saved, setSaved] = useState(false);
  const cloudEnabled = !!(window.Cloud && window.Cloud.enabled);

  useEffect(() => {
    const h = (e) => { if (e.key === 'Escape') onClose(); };
    if (open) window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [open, onClose]);

  if (!open) return null;

  const handleSave = () => {
    TTS.setElevenKey(key.trim());
    setSaved(true);
    setTimeout(() => setSaved(false), 1800);
  };

  const testVoice = async () => {
    TTS.setElevenKey(key.trim());
    try {
      await TTS.speakVoice('The cards have been waiting for you.', VOICES[0]);
    } catch (e) {
      alert('Voice test failed: ' + e.message);
    }
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()} style={{gridTemplateColumns:'1fr', maxWidth:'620px'}}>
        <button className="modal-close" onClick={onClose}>×</button>
        <div>
          {cloudEnabled && <AccountSection user={user}/>}
          <span className="eyebrow">Reader's Throat</span>
          <h2 style={{marginTop:'0.6rem'}}>Voice Settings</h2>
          {cloudEnabled && user ? (
            <p className="lead" style={{marginTop:'1rem', fontSize:'1.1rem'}}>
              You're signed in. Readings are spoken through the hosted voice service —
              no API key needed.
            </p>
          ) : (
            <p className="lead" style={{marginTop:'1rem', fontSize:'1.1rem'}}>
              {cloudEnabled
                ? "Sign in above to use the hosted voices. Or paste your own ElevenLabs key below for offline use."
                : "To let the readers speak in their own voice, connect your ElevenLabs account. Without a key, readings are spoken by your browser's built-in voice."}
            </p>
          )}

          <div style={{marginTop:'2rem'}}>
            <h4>ElevenLabs API Key</h4>
            <input className="input" type="password"
                   placeholder="sk_..."
                   value={key}
                   style={{marginTop:'0.6rem'}}
                   onChange={e => setKey(e.target.value)}/>
            <p className="muted" style={{fontSize:'0.85rem', marginTop:'0.6rem', fontStyle:'italic'}}>
              Stored locally in your browser. Never sent anywhere else.
            </p>
          </div>

          <Divider glyph="mark"/>

          <div>
            <h4>Configured Voices</h4>
            <div style={{marginTop:'1rem', display:'flex', flexDirection:'column', gap:'0.6rem'}}>
              {VOICES.map(v => (
                <div key={v.id} style={{display:'flex', alignItems:'center', gap:'1rem',
                                         padding:'0.7rem 1rem', border:'1px solid var(--gold-faint)',
                                         background:'rgba(10, 6, 18, 0.4)'}}>
                  <div className="voice-portrait" style={{width:36, height:36}}>
                    <Sigil name={v.glyph}/>
                  </div>
                  <div style={{flex:1}}>
                    <div className="voice-name" style={{fontSize:'0.75rem'}}>{v.name}</div>
                    <div style={{fontFamily:'var(--font-display)', fontSize:'0.6rem',
                                 letterSpacing:'0.25em', color: v.voiceId ? 'var(--gold)' : 'var(--ash-dim)'}}>
                      {v.voiceId ? `· ID: ${v.voiceId.slice(0, 10)}… ·` : '· not yet voiced — browser fallback ·'}
                    </div>
                  </div>
                </div>
              ))}
            </div>
          </div>

          <div style={{marginTop:'2rem', display:'flex', gap:'1rem', justifyContent:'center', flexWrap:'wrap'}}>
            <button className="btn ghost small" onClick={testVoice}>Test Voice</button>
            <button className="btn primary small" onClick={handleSave}>
              {saved ? 'Saved ✓' : 'Save Key'}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────
// Account section — magic-link sign in / sign out, shown only when cloud is configured.
// ────────────────────────────────────────────────────────────────
function AccountSection({ user }) {
  const [email, setEmail] = useState('');
  const [status, setStatus] = useState(null); // null | 'sending' | 'sent' | 'error'
  const [errMsg, setErrMsg] = useState('');

  const send = async () => {
    const v = email.trim();
    if (!v) return;
    setStatus('sending');
    setErrMsg('');
    try {
      await window.Cloud.signInWithMagicLink(v);
      setStatus('sent');
    } catch (e) {
      setStatus('error');
      setErrMsg(e?.message || 'Sign-in failed');
    }
  };

  const out = async () => {
    await window.Cloud.signOut();
  };

  return (
    <div style={{marginBottom:'2rem'}}>
      <span className="eyebrow">The Long Memory</span>
      <h2 style={{marginTop:'0.6rem'}}>{user ? 'Your Account' : 'Sign In'}</h2>
      {user ? (
        <div style={{marginTop:'1rem'}}>
          <p className="lead" style={{fontSize:'1.05rem'}}>
            Signed in as <em style={{color:'var(--gold)'}}>{user.email}</em>.
            Your readings are kept in the long memory — returnable from any device.
          </p>
          <div style={{marginTop:'1rem'}}>
            <button className="btn ghost small" onClick={out}>Sign Out</button>
          </div>
        </div>
      ) : (
        <div style={{marginTop:'1rem'}}>
          <p className="lead" style={{fontSize:'1.05rem'}}>
            Sign in to keep your readings across devices and to let the readers
            speak in their own voice. We send a one-time link to your inbox —
            no password to remember.
          </p>
          {status === 'sent' ? (
            <p className="muted" style={{marginTop:'1.2rem', fontStyle:'italic'}}>
              ✨ A sign-in link has been sent to <em>{email}</em>.
              Open it in this browser to return to the cards.
            </p>
          ) : (
            <div style={{display:'flex', gap:'0.6rem', marginTop:'1rem', flexWrap:'wrap'}}>
              <input className="input" type="email"
                     placeholder="your@email.com"
                     value={email}
                     style={{flex:1, minWidth:'220px'}}
                     onChange={e => setEmail(e.target.value)}
                     onKeyDown={e => { if (e.key === 'Enter') send(); }}/>
              <button className="btn primary small" onClick={send}
                      disabled={status === 'sending' || !email.trim()}>
                {status === 'sending' ? 'Sending…' : 'Send Link'}
              </button>
            </div>
          )}
          {status === 'error' && (
            <p className="muted" style={{marginTop:'0.6rem', color:'var(--rust)'}}>{errMsg}</p>
          )}
        </div>
      )}
      <Divider glyph="mark"/>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────
// Footer
// ────────────────────────────────────────────────────────────────
function Footer() {
  return (
    <footer className="footer">
      <div className="glyph"><Sigil name="mark"/></div>
      <p>"The cards reveal not the future, but the question you came to ask."</p>
      <div className="copyright">Veiled · Tarot · MMXXVI</div>
    </footer>
  );
}

// ────────────────────────────────────────────────────────────────
// Phase rail (for reading flow)
// ────────────────────────────────────────────────────────────────
function PhaseRail({ steps, current }) {
  return (
    <div className="phase-rail">
      {steps.map((s, i) => {
        const state = i < current ? 'done' : i === current ? 'active' : '';
        return (
          <div key={s} className={`phase-step ${state}`}>
            <span className="dot"></span>
            <span>{s}</span>
            <span className="line"></span>
          </div>
        );
      })}
    </div>
  );
}

// ────────────────────────────────────────────────────────────────
// Local storage hook
// ────────────────────────────────────────────────────────────────
function useLocal(key, initial) {
  const [val, setVal] = useState(() => {
    try {
      const stored = localStorage.getItem(key);
      return stored ? JSON.parse(stored) : initial;
    } catch { return initial; }
  });
  useEffect(() => {
    try { localStorage.setItem(key, JSON.stringify(val)); } catch {}
  }, [key, val]);
  return [val, setVal];
}

// Expose
Object.assign(window, { TarotCard, Divider, PanelCorners, Nav, Footer, PhaseRail, useLocal, SettingsPanel });
