// screens-detail.jsx — Psychologist detail page + booking

function DetailScreen({ psyId, setRoute, saved, toggleSave, setToast, openChat, authUser, requireAuth, openEditProfile }) {
  const { t, lang } = useLang();
  const [psy, setPsy] = useState(null);
  const [reviews, setReviews] = useState([]);
  const [tab, setTab] = useState('overview');
  const [loadingPsy, setLoadingPsy] = useState(true);

  useEffect(() => {
    API.getPsychologist(psyId)
      .then(data => { setPsy(data); setLoadingPsy(false); })
      .catch(() => setLoadingPsy(false));
    API.getReviews(psyId).then(setReviews).catch(() => {});
  }, [psyId]);

  if (loadingPsy) {
    return (
      <div className="page wide" style={{ paddingTop: 60, textAlign: 'center' }}>
        <Icon name="sync" style={{ fontSize: 36, color: 'var(--fg3)' }} />
        <p style={{ color: 'var(--fg2)', marginTop: 12 }}>{t('detail_loading')}</p>
      </div>
    );
  }

  if (!psy) {
    return (
      <div className="page narrow" style={{ paddingTop: 60, textAlign: 'center' }}>
        <h2 className="display" style={{ fontSize: 24 }}>{t('detail_not_found')}</h2>
        <button className="btn ghost" style={{ marginTop: 20 }} onClick={() => setRoute('directory')}>
          <Icon name="arrow_back" className="sm" /> {t('detail_back_dir')}
        </button>
      </div>
    );
  }

  const approach = APPROACHES.find(a => a.id === psy.primaryApproach);
  const isSaved = saved.has(psy.id);

  return (
    <div className="page wide">
      {/* breadcrumb */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 18, fontSize: 13, color: 'var(--fg2)' }}>
        <button className="btn link" onClick={() => setRoute('directory')} style={{ fontSize: 13 }}>
          <Icon name="arrow_back" className="sm" /> {t('detail_all_psys')}
        </button>
      </div>

      <div className="detail">
        {/* LEFT: profile */}
        <div>
          <div className="detail-hero">
            <Avatar psy={psy} />
            <div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
                <h1 className="name display">{psy.name}</h1>
                {psy.verified && (
                  <a href="https://www.psyboard.org.cy/en/psyboard/registered-psychologists/"
                    target="_blank" rel="noreferrer"
                    style={{ textDecoration: 'none' }}
                    title={lang === 'el' ? 'Επαληθεύτηκε έναντι του μητρώου ΠΣΨΨ' : 'Verified against PSYP registry'}>
                    <span className="verified-badge" style={{ cursor: 'pointer' }}>
                      <Icon name="verified" /> {t('profile_verified')}
                    </span>
                  </a>
                )}
              </div>
              <div className="creds" style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
                <span>{psy.credentials}</span>
                {psy.license_number && (
                  <a href="https://www.psyboard.org.cy/en/psyboard/registered-psychologists/"
                    target="_blank" rel="noreferrer"
                    style={{ display: 'inline-flex', alignItems: 'center', gap: 4, fontSize: 12, fontWeight: 600,
                      color: 'var(--psy-accent)', textDecoration: 'none', padding: '2px 8px',
                      background: 'var(--psy-accent-soft)', borderRadius: 999 }}>
                    <Icon name="badge" className="sm" style={{ fontSize: 13 }} />
                    {psy.license_number}
                    <Icon name="open_in_new" className="sm" style={{ fontSize: 11, opacity: 0.7 }} />
                  </a>
                )}
              </div>
              <div className="row-meta">
                <span className="item"><Icon name="place" /> {psy.district}</span>
                <span className="item"><Icon name="translate" /> {psy.languages.join(' · ')}</span>
                <span className="item"><Icon name="work_history" /> {psy.yearsExperience} {t('detail_years')}</span>
                {psy.gesy && <span className="item" style={{ color: 'var(--psy-leaf)' }}><Icon name="health_and_safety" /> {t('detail_gesy')}</span>}
              </div>

              <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginTop: 16 }}>
                <Stars value={psy.rating} size={18} />
                <strong style={{ fontSize: 16 }}>{psy.rating}</strong>
                <span style={{ color: 'var(--fg2)' }}>· {psy.reviewCount} {t('detail_verified_reviews')}</span>
                <span style={{ color: 'var(--psy-leaf)', fontSize: 13, fontWeight: 600, marginLeft: 'auto' }}>
                  <Icon name="bolt" className="sm" /> {t('detail_replies')} {psy.responseHours}{t('detail_replies_h')}
                </span>
              </div>
              {psy.verified_at && (
                <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 8, fontSize: 11.5, color: 'var(--psy-leaf)' }}>
                  <Icon name="verified_user" className="sm" style={{ fontSize: 13 }} />
                  {lang === 'el' ? 'Τελευταία επαλήθευση ΠΣΨΨ: ' : 'Last PSYP verification: '}
                  <strong>{new Date(psy.verified_at).toLocaleDateString(lang === 'el' ? 'el-GR' : 'en-GB', { day: 'numeric', month: 'long', year: 'numeric' })}</strong>
                </div>
              )}

              <div style={{ display: 'flex', gap: 10, marginTop: 18, flexWrap: 'wrap', alignItems: 'center' }}>
                {psy.chatEnabled && (
                  <button className="btn ghost" onClick={() => openChat(psy.id)}>
                    <Icon name="chat_bubble_outline" className="sm" /> {t('detail_msg')}
                  </button>
                )}
                <button className="btn ghost" onClick={() => { toggleSave(psy.id); setToast(isSaved ? t('detail_removed') : t('detail_saved_toast')); }}>
                  <Icon name="bookmark" className="sm" style={{ fontVariationSettings: isSaved ? "'FILL' 1" : "'FILL' 0", color: isSaved ? 'var(--psy-accent)' : 'inherit' }} />
                  {isSaved ? t('detail_saved') : t('detail_save')}
                </button>
                <button className="btn ghost"><Icon name="share" className="sm" /> {t('detail_share')}</button>
                {authUser && authUser.role === 'admin' && openEditProfile && (
                  <button className="btn primary sm" style={{ marginLeft: 'auto' }}
                    onClick={() => openEditProfile(psy.id)}>
                    <Icon name="edit" className="sm" /> {t('detail_edit')}
                  </button>
                )}
              </div>
            </div>
          </div>

          {/* Tabs */}
          <div className="tabs">
            <button className={`tab ${tab === 'overview' ? 'active' : ''}`} onClick={() => setTab('overview')}>{t('tab_overview')}</button>
            <button className={`tab ${tab === 'approach' ? 'active' : ''}`} onClick={() => setTab('approach')}>{t('tab_approach')}</button>
            <button className={`tab ${tab === 'reviews' ? 'active' : ''}`} onClick={() => setTab('reviews')}>{t('tab_reviews')} ({psy.reviewCount})</button>
            <button className={`tab ${tab === 'location' ? 'active' : ''}`} onClick={() => setTab('location')}>{t('tab_location')}</button>
          </div>

          {tab === 'overview' && <OverviewTab psy={psy} />}
          {tab === 'approach' && <ApproachTab psy={psy} approach={approach} />}
          {tab === 'reviews' && <ReviewsTab psy={psy} reviews={reviews} setReviews={setReviews} authUser={authUser} requireAuth={requireAuth} setToast={setToast} />}
          {tab === 'location' && <LocationTab psy={psy} />}
        </div>

        {/* RIGHT: booking card */}
        <BookingCard psy={psy} setToast={setToast} authUser={authUser} requireAuth={requireAuth} setRoute={setRoute} />
      </div>
    </div>
  );
}

function OverviewTab({ psy }) {
  const { t } = useLang();
  return (
    <div className="col" style={{ gap: 28 }}>
      <section>
        <h3 className="display" style={{ fontSize: 22, marginBottom: 10 }}>{t('profile_about_h')}</h3>
        <p style={{ color: 'var(--psy-ink)', fontSize: 15, lineHeight: 1.65 }}>{psy.longBio}</p>
      </section>

      <section>
        <h3 className="display" style={{ fontSize: 22, marginBottom: 14 }}>{t('profile_specs_h')}</h3>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
          {psy.specializations.map(s => {
            const x = SPECIALIZATIONS.find(z => z.id === s);
            return <span key={s} className="tag" style={{ padding: '8px 14px', fontSize: 13 }}>{x?.name}</span>;
          })}
        </div>
      </section>

      <section>
        <h3 className="display" style={{ fontSize: 22, marginBottom: 14 }}>{t('profile_edu_h')}</h3>
        <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>
          {psy.education.map((e, i) => (
            <li key={i} style={{ display: 'grid', gridTemplateColumns: '80px 1fr', gap: 16, padding: '10px 0', borderTop: i ? '1px solid var(--psy-rule)' : '0' }}>
              <span style={{ color: 'var(--fg2)', fontSize: 13, fontWeight: 600 }}>{e.year}</span>
              <span style={{ fontSize: 14 }}>{e.text}</span>
            </li>
          ))}
        </ul>
      </section>

      <section>
        <h3 className="display" style={{ fontSize: 22, marginBottom: 14 }}>{t('profile_work_h')}</h3>
        <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>
          {psy.experience.map((e, i) => (
            <li key={i} style={{ display: 'grid', gridTemplateColumns: '110px 1fr', gap: 16, padding: '10px 0', borderTop: i ? '1px solid var(--psy-rule)' : '0' }}>
              <span style={{ color: 'var(--fg2)', fontSize: 13, fontWeight: 600 }}>{e.year}</span>
              <span style={{ fontSize: 14 }}>{e.text}</span>
            </li>
          ))}
        </ul>
      </section>
    </div>
  );
}

function ApproachTab({ psy, approach }) {
  const { t } = useLang();
  // Guard — profile not yet filled in
  if (!approach) {
    return (
      <div className="col" style={{ gap: 24 }}>
        <div className="card" style={{ padding: 40, textAlign: 'center', background: 'var(--psy-surface)', borderColor: 'transparent' }}>
          <Icon name="psychology" style={{ fontSize: 40, color: 'var(--fg3)', display: 'block', margin: '0 auto 14px' }} />
          <div style={{ fontSize: 16, fontWeight: 600, color: 'var(--fg2)' }}>{t('approach_empty')}</div>
          <div style={{ fontSize: 14, color: 'var(--fg3)', marginTop: 6, lineHeight: 1.55 }}>
            {t('approach_empty_sub')}
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="col" style={{ gap: 24 }}>
      <div className="card" style={{ padding: 28, background: 'var(--psy-surface)', borderColor: 'transparent' }}>
        <span className="eyebrow">{t('profile_primary')}</span>
        <h2 className="display" style={{ fontSize: 30, marginTop: 8 }}>{approach.long}</h2>
        <p style={{ color: 'var(--fg2)', marginTop: 12, fontSize: 15, lineHeight: 1.6, maxWidth: 640 }}>{approach.short}</p>
      </div>

      {psy.approaches.length > 1 && (
        <section>
          <h3 className="display" style={{ fontSize: 20, marginBottom: 12, fontWeight: 600 }}>{t('profile_also')}</h3>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 10 }}>
            {psy.approaches.filter(a => a !== psy.primaryApproach).map(a => {
              const ap = APPROACHES.find(x => x.id === a);
              return (
                <div key={a} className="card" style={{ padding: 14 }}>
                  <div style={{ fontWeight: 600, fontSize: 14 }}>{ap?.long}</div>
                  <div style={{ fontSize: 12, color: 'var(--fg2)', marginTop: 4, lineHeight: 1.5 }}>{ap?.short}</div>
                </div>
              );
            })}
          </div>
        </section>
      )}

      <section>
        <h3 className="display" style={{ fontSize: 20, marginBottom: 12, fontWeight: 600 }}>{t('profile_issues')}</h3>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))', gap: 10 }}>
          {psy.specializations.map(s => {
            const x = SPECIALIZATIONS.find(z => z.id === s);
            return (
              <div key={s} style={{ display: 'flex', gap: 10, alignItems: 'center', padding: '10px 14px', background: 'white', border: '1px solid var(--psy-rule)', borderRadius: 12 }}>
                <Icon name="check_circle" style={{ color: 'var(--psy-leaf)' }} />
                <span style={{ fontSize: 14, fontWeight: 500 }}>{x?.name}</span>
              </div>
            );
          })}
        </div>
      </section>
    </div>
  );
}

function ReviewsTab({ psy, reviews, setReviews, authUser, requireAuth, setToast }) {
  const { t } = useLang();
  const [composing, setComposing] = useState(false);
  const [rating, setRating] = useState(5);
  const [body, setBody] = useState('');
  const [sessions, setSessions] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [pendingReview, setPendingReview] = useState(null); // user's own pending review

  // Check if logged-in user has a pending review for this psychologist
  useEffect(function() {
    if (!authUser) return;
    const token = JSON.parse(localStorage.getItem('psyche-auth') || '{}').token;
    if (!token) return;
    fetch('/api/reviews/' + psy.id + '/mine', { headers: { Authorization: 'Bearer ' + token } })
      .then(function(r) { return r.json(); })
      .then(function(d) { if (d && d.status === 'pending') setPendingReview(d); })
      .catch(function() {});
  }, [authUser, psy.id]);

  async function submitReview() {
    if (!requireAuth()) return;
    if (!body.trim()) return;
    setSubmitting(true);
    try {
      await API.postReview(psy.id, { rating, body, sessions: Number(sessions) || 0 });
      setComposing(false);
      setBody(''); setRating(5); setSessions('');
      setToast('Review submitted — it will appear after admin verification.');
      // Show pending notice immediately
      setPendingReview({ rating, body, status: 'pending', verified: false });
    } catch (e) {
      setToast(e.message);
    } finally {
      setSubmitting(false);
    }
  }

  // Real bar chart from actual approved reviews
  const hasReviews = reviews.length > 0;
  const buckets = [5, 4, 3, 2, 1].map(s => ({
    star: s,
    count: reviews.filter(function(r) { return r.rating === s; }).length,
    pct: hasReviews
      ? Math.round((reviews.filter(function(r) { return r.rating === s; }).length / reviews.length) * 100)
      : 0,
  }));

  return (
    <div className="col" style={{ gap: 24 }}>
      {/* Rating summary — only when there are real reviews */}
      {hasReviews ? (
        <div style={{ display: 'grid', gridTemplateColumns: '200px 1fr', gap: 40, alignItems: 'center', padding: 24, background: 'white', border: '1px solid var(--psy-rule)', borderRadius: 16 }}>
          <div style={{ textAlign: 'center' }}>
            <div style={{ fontFamily: 'var(--font-display)', fontSize: 56, fontWeight: 500, letterSpacing: '-0.03em', lineHeight: 1 }}>{psy.rating}</div>
            <Stars value={psy.rating} size={20} />
            <div style={{ fontSize: 13, color: 'var(--fg2)', marginTop: 6 }}>{reviews.length} {t('profile_reviews')}</div>
          </div>
          <div>
            {buckets.map(b => (
              <div key={b.star} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '4px 0', fontSize: 12 }}>
                <span style={{ width: 36, color: 'var(--fg2)' }}>{b.star} {t('rev_star')}</span>
                <div style={{ flex: 1, height: 6, background: 'var(--psy-rule)', borderRadius: 999, overflow: 'hidden' }}>
                  <div style={{ width: `${b.pct}%`, height: '100%', background: 'var(--psy-accent)', transition: 'width 0.4s ease' }}></div>
                </div>
                <span style={{ width: 40, textAlign: 'right', color: 'var(--fg2)' }}>{b.pct}%</span>
              </div>
            ))}
          </div>
        </div>
      ) : (
        <div style={{ padding: '28px 24px', background: 'white', border: '1px solid var(--psy-rule)', borderRadius: 16, textAlign: 'center' }}>
          <Icon name="star_border" style={{ fontSize: 36, color: 'var(--fg3)', display: 'block', margin: '0 auto 10px' }} />
          <div style={{ fontWeight: 600, fontSize: 15, color: 'var(--fg2)' }}>{t('rev_no_reviews')}</div>
          <div style={{ fontSize: 13, color: 'var(--fg3)', marginTop: 4 }}>{t('rev_no_reviews_sub')}</div>
        </div>
      )}

      <div className="card" style={{ padding: 20, background: 'var(--psy-leaf-soft)', borderColor: 'transparent' }}>
        <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start' }}>
          <Icon name="verified" style={{ color: 'var(--psy-leaf)', fontSize: 22 }} />
          <div>
            <strong style={{ fontSize: 14, color: 'var(--psy-leaf)' }}>{t('rev_how_title')}</strong>
            <p style={{ fontSize: 13, color: 'var(--psy-ink)', marginTop: 4, lineHeight: 1.55, maxWidth: 600 }}>
              {t('rev_how_body')}
            </p>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: 10 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12 }}>
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 9px', background: 'var(--psy-leaf-soft)', color: 'var(--psy-leaf)', borderRadius: 999, fontWeight: 600, whiteSpace: 'nowrap' }}>
                  <Icon name="verified" className="sm" style={{ fontSize: 13 }} /> {t('rev_verified_short')}
                </span>
                <span style={{ color: 'var(--fg2)' }}>{t('rev_verified_desc')}</span>
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12 }}>
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 9px', background: 'var(--psy-surface)', border: '1px solid var(--psy-rule)', color: 'var(--fg3)', borderRadius: 999, fontWeight: 500, whiteSpace: 'nowrap' }}>
                  <Icon name="info" className="sm" style={{ fontSize: 13 }} /> {t('rev_ext_short')}
                </span>
                <span style={{ color: 'var(--fg2)' }}>{t('rev_external_desc')}</span>
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* Pending review notice */}
      {pendingReview && (
        <div style={{ display: 'flex', gap: 12, alignItems: 'flex-start', padding: '14px 18px', background: 'var(--psy-accent-soft)', borderRadius: 14, border: '1px solid transparent' }}>
          <Icon name="pending" style={{ color: 'var(--psy-accent)', flexShrink: 0, marginTop: 2 }} />
          <div>
            <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--psy-accent)' }}>{t('rev_pending_h')}</div>
            <div style={{ fontSize: 13, color: 'var(--fg2)', marginTop: 3, lineHeight: 1.5 }}>
              {t('rev_pending_body')}
              {pendingReview.verified && (
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, marginLeft: 8, color: 'var(--psy-leaf)', fontWeight: 600 }}>
                  <Icon name="verified" className="sm" /> {t('rev_booking_conf')}
                </span>
              )}
            </div>
          </div>
        </div>
      )}

      {/* Write a review */}
      {!pendingReview && !composing ? (
        <button className="btn ghost" style={{ alignSelf: 'flex-start' }} onClick={function() { requireAuth(function() { setComposing(true); }); }}>
          <Icon name="rate_review" className="sm" /> {t('rev_write')}
        </button>
      ) : !pendingReview && composing && (
        <div className="card" style={{ padding: 22 }}>
          <strong style={{ fontSize: 14 }}>{t('rev_leave')}</strong>
          <div style={{ display: 'flex', gap: 6, margin: '14px 0 4px' }}>
            {[1,2,3,4,5].map(n => (
              <button key={n} onClick={() => setRating(n)}
                style={{ background: 'none', border: 0, padding: 2, cursor: 'pointer', fontSize: 22,
                  color: n <= rating ? 'var(--psy-accent)' : 'var(--psy-rule)',
                  fontVariationSettings: n <= rating ? "'FILL' 1" : "'FILL' 0" }}>★</button>
            ))}
          </div>
          <textarea className="textarea" placeholder={t('rev_placeholder')} value={body} onChange={e => setBody(e.target.value)} style={{ marginTop: 10 }} />
          <input className="input" type="number" min="0" placeholder={t('rev_sessions_q')} value={sessions} onChange={e => setSessions(e.target.value)} style={{ marginTop: 8 }} />
          <div style={{ display: 'flex', gap: 8, marginTop: 14, justifyContent: 'flex-end' }}>
            <button className="btn ghost" onClick={() => setComposing(false)}>{t('rev_cancel')}</button>
            <button className="btn primary" disabled={!body.trim() || submitting} onClick={submitReview}>
              {submitting ? t('rev_submitting') : t('rev_submit')}
            </button>
          </div>
        </div>
      )}

      {reviews.length > 0 && (
        <div style={{ background: 'white', border: '1px solid var(--psy-rule)', borderRadius: 16, padding: '4px 24px' }}>
          {reviews.map(r => (
            <div key={r.id} className="review">
              <div className="review-head">
                <div className="avatar-sm" style={{ background: avatarBg('a') }}>{r.initials}</div>
                <div>
                  <div className="review-author">{r.author}</div>
                  <div className="review-meta">{r.when_text || r.when} · {t('rev_after')} {r.sessions} {t('rev_sessions')}</div>
                </div>
                <div style={{ marginLeft: 'auto' }}>
                  <Stars value={r.rating} />
                </div>
              </div>
              <div className="review-body">{r.body}</div>
              <div style={{ marginTop: 8 }}>
                {r.verified
                  ? <VerifiedBadge>{t('rev_verified_lbl')}</VerifiedBadge>
                  : (
                    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 11.5, fontWeight: 500, color: 'var(--fg3)', background: 'var(--psy-surface)', border: '1px solid var(--psy-rule)', borderRadius: 999, padding: '3px 10px' }}>
                      <Icon name="info" className="sm" style={{ fontSize: 13 }} /> {t('rev_external_lbl')}
                    </span>
                  )
                }
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function LocationTab({ psy }) {
  const { t } = useLang();
  const [coords, setCoords] = React.useState(
    psy.lat && psy.lon ? { lat: psy.lat, lon: psy.lon } : null
  );

  // If no coords in DB, geocode client-side from address
  React.useEffect(() => {
    if (coords) return;
    if (!psy.address) return;
    const q = encodeURIComponent(psy.address + (psy.district ? `, ${psy.district}` : '') + ', Cyprus');
    fetch(`https://nominatim.openstreetmap.org/search?q=${q}&format=json&limit=1&countrycodes=cy`, {
      headers: { 'Accept-Language': 'en' }
    })
      .then(r => r.json())
      .then(data => { if (data[0]) setCoords({ lat: parseFloat(data[0].lat), lon: parseFloat(data[0].lon) }); })
      .catch(() => {});
  }, [psy.address]);

  return (
    <div className="col" style={{ gap: 16 }}>
      {coords ? (
        <div style={{ borderRadius: 16, overflow: 'hidden', border: '1px solid var(--psy-rule)', height: 220 }}>
          <iframe
            src={`https://www.openstreetmap.org/export/embed.html?bbox=${coords.lon-0.005},${coords.lat-0.003},${coords.lon+0.005},${coords.lat+0.003}&layer=mapnik&marker=${coords.lat},${coords.lon}`}
            width="100%" height="100%" style={{ border: 0 }} title="map" loading="lazy" />
        </div>
      ) : (
        <div className="map">
          <div className="pin">{psy.district}</div>
        </div>
      )}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
        <div className="card" style={{ padding: 20 }}>
          <span className="eyebrow muted">{t('address_label')}</span>
          <div style={{ marginTop: 8, fontSize: 15, lineHeight: 1.5 }}>{psy.address}</div>
          <div style={{ display: 'flex', gap: 8, marginTop: 14, flexWrap: 'wrap' }}>
            {[
              { label: 'Google Maps', icon: 'map', href: `https://www.google.com/maps/dir/?api=1&destination=${encodeURIComponent((psy.address||'') + ', Cyprus')}` },
              { label: 'Apple Maps', icon: 'map', href: `http://maps.apple.com/?daddr=${encodeURIComponent((psy.address||'') + ', Cyprus')}` },
              { label: 'Waze', icon: 'navigation', href: `https://waze.com/ul?q=${encodeURIComponent((psy.address||'') + ', Cyprus')}&navigate=yes` },
            ].map(app => (
              <a key={app.label} className="btn ghost sm"
                style={{ display: 'inline-flex', alignItems: 'center', gap: 5, textDecoration: 'none' }}
                href={app.href} target="_blank" rel="noreferrer">
                <Icon name={app.icon} className="sm" /> {app.label}
              </a>
            ))}
          </div>
        </div>
        <div className="card" style={{ padding: 20 }}>
          <span className="eyebrow muted">{t('formats_label')}</span>
          <div style={{ display: 'flex', gap: 8, marginTop: 8, flexWrap: 'wrap' }}>
            {psy.modes.map(m => (
              <span key={m} className="tag ink">
                <Icon name={m === 'online' ? 'videocam' : 'meeting_room'} className="sm" />
                {m === 'online' ? t('loc_online_sessions') : t('lbl_inperson')}
              </span>
            ))}
          </div>
          <div style={{ marginTop: 14, fontSize: 13, color: 'var(--fg2)' }}>
            {t('loc_session_len')} <strong style={{ color: 'var(--psy-ink)' }}>{psy.sessionLengthMin || 50} {t('loc_minutes')}</strong>
            <br />
            {t('cancellation')}
          </div>
        </div>
      </div>
    </div>
  );
}

// ===========================================================
//  BOOKING SIDEBAR
// ===========================================================
function BookingCard({ psy, setToast, authUser, requireAuth, setRoute }) {
  const { t } = useLang();
  const today = new Date();
  const [dayIdx, setDayIdx] = useState(0);
  const [slot, setSlot] = useState(null);
  const [mode, setMode] = useState(psy.modes[0]);
  const [step, setStep] = useState('pick');
  const [booking, setBooking] = useState(false);

  // Live availability from database
  const [availDays, setAvailDays]   = useState(null);  // null=loading, number[]=day_of_week values
  const [liveSlots, setLiveSlots]   = useState([]);
  const [slotsLoading, setSlotsLoading] = useState(false);

  // Check if this user already has a booking with this psychologist
  const [existingBooking, setExistingBooking] = useState(null);
  useEffect(() => {
    if (!authUser) return;
    const raw = localStorage.getItem('psyche-auth');
    const token = raw ? JSON.parse(raw).token : null;
    if (!token) return;
    fetch('/api/bookings/mine', { headers: { Authorization: 'Bearer ' + token } })
      .then(r => r.json())
      .then(data => {
        if (Array.isArray(data)) {
          const match = data.find(b => b.psy_id === psy.id && b.status !== 'declined');
          if (match) setExistingBooking(match);
        }
      })
      .catch(() => {});
  }, [authUser, psy.id]);

  // Fetch which days-of-week this psychologist is available (from DB)
  useEffect(() => {
    API.getAvailableDays(psy.id)
      .then(days => {
        setAvailDays(Array.isArray(days) ? days : []);
        // auto-select first available day in the 7-day window
        const window7 = Array.from({ length: 7 }, (_, i) => {
          const d = new Date(); d.setDate(d.getDate() + i); return d.getDay();
        });
        const firstIdx = window7.findIndex(dow => (Array.isArray(days) ? days : []).includes(dow));
        if (firstIdx >= 0) setDayIdx(firstIdx);
      })
      .catch(() => setAvailDays([]));
  }, [psy.id]);

  // Fetch live time slots whenever the selected day changes
  useEffect(() => {
    const d = new Date(); d.setDate(d.getDate() + dayIdx);
    const dateStr = d.toISOString().slice(0, 10);
    setSlotsLoading(true);
    setSlot(null);
    API.getSlots(psy.id, dateStr)
      .then(s => {
        // API returns [{time, available}] — extract available time strings only
        const times = Array.isArray(s)
          ? s.filter(x => x.available !== false).map(x => x.time || x)
          : [];
        setLiveSlots(times);
        setSlotsLoading(false);
      })
      .catch(() => { setLiveSlots([]); setSlotsLoading(false); });
  }, [dayIdx, psy.id]);

  // ── CONFIRMED ──────────────────────────────────────────────
  if (existingBooking && existingBooking.status === 'confirmed') {
    const b = existingBooking;
    const dateStr = b.date ? new Date(b.date).toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'long' }) : b.date;
    const [year, month, day] = (b.date || '2026-01-01').split('-').map(Number);
    const [hour, min] = (b.time || '09:00').split(':').map(Number);
    const pad = n => String(n).padStart(2, '0');
    const startStr = `${year}${pad(month)}${pad(day)}T${pad(hour)}${pad(min)}00`;
    const endStr   = `${year}${pad(month)}${pad(day)}T${pad(hour + 1)}${pad(min)}00`;
    const title    = encodeURIComponent('Session with ' + psy.name);
    const details  = encodeURIComponent('Psychology session booked via Psyche (psyche.cy)');
    const loc      = encodeURIComponent(b.mode === 'online' ? 'Online video call' : 'Psychologist office');
    const googleUrl  = `https://www.google.com/calendar/render?action=TEMPLATE&text=${title}&dates=${startStr}/${endStr}&details=${details}&location=${loc}`;
    const icsUrl     = `/api/bookings/${b.id}/calendar.ics`;

    return (
      <aside className="booking-card">
        <div style={{ textAlign: 'center', padding: '4px 0' }}>
          <div style={{ width: 52, height: 52, borderRadius: '50%', background: 'var(--psy-leaf-soft)', display: 'grid', placeItems: 'center', margin: '0 auto 12px' }}>
            <Icon name="event_available" style={{ color: 'var(--psy-leaf)', fontSize: 24 }} />
          </div>
          <h3 className="display" style={{ fontSize: 19, fontWeight: 600, color: 'var(--psy-leaf)' }}>{t('book_confirmed_h')}</h3>
          <p style={{ color: 'var(--fg2)', fontSize: 12.5, marginTop: 5, lineHeight: 1.5 }}>
            {psy.name.split(' ').slice(-1)[0]} {t('book_confirmed_p')}
          </p>
        </div>
        <div className="divider" />
        <div style={{ fontSize: 13, color: 'var(--fg2)' }}>
          {[[t('book_date'), dateStr], [t('book_time'), b.time], [t('book_format'), b.mode === 'online' ? t('lbl_online') : t('lbl_inperson')]].map(([k, v]) => (
            <div key={k} style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0' }}>
              <span>{k}</span><strong style={{ color: 'var(--psy-ink)' }}>{v}</strong>
            </div>
          ))}
        </div>
        <div className="divider" />
        <div style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--fg2)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 8 }}>
          {t('book_add_cal')}
        </div>
        {b.mode === 'online' && b.daily_room_name && setRoute && (
          <>
            <div className="divider" />
            <button
              className="btn accent"
              style={{ width: '100%', justifyContent: 'center' }}
              onClick={() => setRoute('video-call', { id: String(b.id) })}>
              <Icon name="videocam" className="sm" /> Join Video Call
            </button>
          </>
        )}
        <div style={{ display: 'flex', gap: 8, flexDirection: 'column', marginTop: 8 }}>
          <a href={googleUrl} target="_blank" rel="noreferrer" className="btn ghost sm" style={{ justifyContent: 'center', textDecoration: 'none' }}>
            <Icon name="event" className="sm" /> {t('book_google')}
          </a>
          <a href={icsUrl} className="btn ghost sm" style={{ justifyContent: 'center', textDecoration: 'none' }}>
            <Icon name="download" className="sm" /> {t('book_ics')}
          </a>
        </div>
        <button className="btn link" style={{ marginTop: 14, fontSize: 12, color: 'var(--fg3)', width: '100%', textAlign: 'center' }} onClick={() => setExistingBooking(null)}>
          {t('book_change')}
        </button>
      </aside>
    );
  }

  // ── PENDING ────────────────────────────────────────────────
  if (existingBooking && existingBooking.status === 'pending') {
    const b = existingBooking;
    const dateStr = b.date ? new Date(b.date).toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'short' }) : b.date;
    return (
      <aside className="booking-card">
        <div style={{ textAlign: 'center', padding: '4px 0' }}>
          <div style={{ width: 52, height: 52, borderRadius: '50%', background: 'var(--psy-accent-soft)', display: 'grid', placeItems: 'center', margin: '0 auto 12px' }}>
            <Icon name="pending" style={{ color: 'var(--psy-accent)', fontSize: 24 }} />
          </div>
          <h3 className="display" style={{ fontSize: 19, fontWeight: 600 }}>{t('book_pending_h')}</h3>
          <p style={{ color: 'var(--fg2)', fontSize: 12.5, marginTop: 5, lineHeight: 1.5 }}>
            {psy.name.split(' ').slice(-1)[0]} {t('book_pending_p')}
          </p>
        </div>
        <div className="divider" />
        <div style={{ fontSize: 13, color: 'var(--fg2)' }}>
          {[[t('book_date'), dateStr], [t('book_time'), b.time], [t('book_format'), b.mode === 'online' ? t('lbl_online') : t('lbl_inperson')]].map(([k, v]) => (
            <div key={k} style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0' }}>
              <span>{k}</span><strong style={{ color: 'var(--psy-ink)' }}>{v}</strong>
            </div>
          ))}
        </div>
        <div className="divider" />
        <div style={{ background: 'var(--psy-surface)', borderRadius: 10, padding: '10px 12px', fontSize: 12, color: 'var(--fg2)', lineHeight: 1.55 }}>
          <Icon name="info" className="sm" style={{ verticalAlign: -3, marginRight: 4 }} />
          {t('book_reply_note')}
        </div>
        <button className="btn ghost block sm" style={{ marginTop: 12 }} onClick={() => setExistingBooking(null)}>
          {t('book_change_time')}
        </button>
      </aside>
    );
  }

  // ── DECLINED ───────────────────────────────────────────────
  if (existingBooking && existingBooking.status === 'declined') {
    return (
      <aside className="booking-card">
        <div style={{ textAlign: 'center', padding: '4px 0' }}>
          <div style={{ width: 52, height: 52, borderRadius: '50%', background: '#FEE2E2', display: 'grid', placeItems: 'center', margin: '0 auto 12px' }}>
            <Icon name="event_busy" style={{ color: 'var(--color-error)', fontSize: 24 }} />
          </div>
          <h3 className="display" style={{ fontSize: 18, fontWeight: 600 }}>{t('book_declined_h')}</h3>
          {existingBooking.decline_reason && (
            <div style={{ background: '#FEF3C7', borderRadius: 10, padding: '10px 12px', marginTop: 10, fontSize: 12.5, color: '#92400E', textAlign: 'left', lineHeight: 1.55 }}>
              <b>Message from {psy.name.split(' ').slice(-1)[0]}:</b> {existingBooking.decline_reason}
            </div>
          )}
          {existingBooking.alt_time && (
            <div style={{ background: 'var(--psy-accent-soft)', borderRadius: 10, padding: '12px 14px', marginTop: 8, textAlign: 'left' }}>
              <div style={{ fontSize: 10.5, fontWeight: 700, color: 'var(--psy-accent)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 4 }}>
                {t('book_proposed')}
              </div>
              <div style={{ fontSize: 15, fontWeight: 600, color: 'var(--psy-ink)' }}>{existingBooking.alt_time}</div>
              <div style={{ marginTop: 8, padding: '8px 10px', background: 'white', borderRadius: 8, fontSize: 12, color: 'var(--fg2)', lineHeight: 1.55 }}>
                <Icon name="phone" className="sm" style={{ verticalAlign: -3, marginRight: 4 }} />
                {t('book_confirm_call')} <strong>{psy.name.split(' ').slice(-1)[0]} {t('book_confirm_call2')}</strong>. {t('book_no_contact')}
              </div>
            </div>
          )}
        </div>
        <div className="divider" />
        <button className="btn primary block" onClick={() => setExistingBooking(null)}>
          <Icon name="event" className="sm" /> {t('book_diff_time')}
        </button>
      </aside>
    );
  }

  const days = Array.from({ length: 7 }, (_, i) => {
    const d = new Date(); d.setDate(today.getDate() + i);
    const dow = d.getDay();
    return {
      date: d,
      label: d.toLocaleDateString('en-GB', { weekday: 'short' }),
      num: d.getDate(),
      dow,
      // has availability if availDays loaded and includes this day-of-week
      has: availDays === null ? false : availDays.includes(dow),
    };
  });
  const selDay = days[dayIdx];

  async function book() {
    if (!requireAuth()) return;
    setBooking(true);
    try {
      await API.postBooking({
        psyId: psy.id,
        psyName: psy.name,
        date: selDay.date.toISOString().slice(0, 10),
        time: slot,
        mode,
      });
      setStep('done');
      setToast('Request sent. ' + psy.name.split(' ').slice(-1)[0] + ' will confirm shortly.');
    } catch (e) {
      setToast(e.message);
    } finally {
      setBooking(false);
    }
  }

  if (step === 'done') {
    return (
      <aside className="booking-card">
        <div style={{ textAlign: 'center', padding: '8px 0' }}>
          <div style={{ width: 52, height: 52, borderRadius: '50%', background: 'var(--psy-leaf-soft)', display: 'grid', placeItems: 'center', margin: '0 auto 12px' }}>
            <Icon name="check" style={{ color: 'var(--psy-leaf)', fontSize: 26 }} />
          </div>
          <h3 className="display" style={{ fontSize: 20, fontWeight: 600 }}>{t('book_sent_h')}</h3>
          <p style={{ color: 'var(--fg2)', fontSize: 12.5, marginTop: 6, lineHeight: 1.5 }}>
            {psy.name.split(' ').slice(-1)[0]} {t('book_sent_p')}
          </p>
        </div>
        <div className="divider" />
        <div style={{ fontSize: 13, color: 'var(--fg2)' }}>
          {[
            [t('book_date'), selDay.date.toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'short' })],
            [t('book_time'), slot],
            [t('book_format'), mode === 'online' ? t('lbl_online') : t('lbl_inperson')],
            [t('book_fee'), '€' + psy.pricePerSession],
          ].map(([k, v]) => (
            <div key={k} style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0' }}>
              <span>{k}</span><strong style={{ color: 'var(--psy-ink)' }}>{v}</strong>
            </div>
          ))}
        </div>
        <div className="divider" />
        <div style={{ background: 'var(--psy-surface)', borderRadius: 10, padding: '10px 12px', fontSize: 12, color: 'var(--fg2)', lineHeight: 1.55 }}>
          <Icon name="schedule" className="sm" style={{ verticalAlign: -3, marginRight: 4 }} />
          {t('book_reply_note2')}
        </div>
      </aside>
    );
  }

  return (
    <aside className="booking-card">
      {psy.introCall && (
        <div style={{ background: 'var(--psy-leaf-soft)', border: '1px solid transparent', borderRadius: 12, padding: 12, marginBottom: 16 }}>
          <div style={{ fontWeight: 600, fontSize: 13, color: 'var(--psy-leaf)' }}>
            <Icon name="phone_in_talk" className="sm" /> {t('book_intro')}
          </div>
          <div style={{ fontSize: 12, color: 'var(--fg2)', marginTop: 4, lineHeight: 1.45 }}>
            {t('book_intro_sub')}
          </div>
        </div>
      )}

      <div className="row spread" style={{ marginBottom: 12 }}>
        <div className="price">€{psy.pricePerSession} <small>/ session</small></div>
        <span style={{ fontSize: 12, color: 'var(--fg2)' }}>{psy.sessionLengthMin || 50} min</span>
      </div>

      {/* Calendar booking — instant confirmation */}
      {psy.modes && psy.modes.length > 0 && setRoute && (
        <button
          className="btn accent"
          style={{ width: '100%', justifyContent: 'center', marginBottom: 12 }}
          onClick={() => requireAuth(() => setRoute('book', psy.id))}>
          <Icon name="event_available" className="sm" />
          {t('book_book_session') || 'Book a session'}
        </button>
      )}

      <div style={{ display: 'flex', gap: 6, marginBottom: 14 }}>
        {psy.modes.map(m => (
          <button key={m}
            onClick={() => setMode(m)}
            className="btn ghost sm"
            style={mode === m ? { background: 'var(--psy-ink)', color: 'white', borderColor: 'var(--psy-ink)' } : null}>
            <Icon name={m === 'online' ? 'videocam' : 'meeting_room'} className="sm" />
            {m === 'online' ? t('lbl_online') : t('lbl_inperson')}
          </button>
        ))}
      </div>

      <div className="field-label">{t('book_pick_day')}</div>
      <div className="day-strip">
        {days.map((d, i) => (
          <div key={i}
            className={`day ${d.has ? 'has' : 'disabled'} ${dayIdx === i ? 'selected' : ''}`}
            onClick={() => d.has && (setDayIdx(i), setSlot(null))}>
            {d.label}
            <span className="num">{d.num}</span>
          </div>
        ))}
      </div>

      <div className="field-label" style={{ marginTop: 14 }}>
        {slotsLoading ? 'Loading times…' : liveSlots.length > 0 ? t('book_avail') : t('book_no_times')}
      </div>
      <div className="slot-grid">
        {slotsLoading ? (
          <button className="slot" disabled style={{ opacity: 0.5 }}>…</button>
        ) : liveSlots.length > 0 ? (
          liveSlots.map(s => (
            <button key={s}
              className={`slot ${slot === s ? 'selected' : ''}`}
              onClick={() => setSlot(s)}>
              {s}
            </button>
          ))
        ) : (
          <button className="slot" disabled>—</button>
        )}
      </div>

      <button className="btn primary block lg" style={{ marginTop: 18 }}
        disabled={!slot || booking}
        onClick={book}>
        {booking ? t('book_sending') : slot ? (t('book_btn_request') + ' ' + selDay.label + ' ' + t('book_btn_at') + ' ' + slot) : t('book_btn_pick')}
      </button>
      {!authUser && slot && (
        <div style={{ fontSize: 12, color: 'var(--fg3)', textAlign: 'center', marginTop: 6 }}>
          {t('book_sign_in_note')}
        </div>
      )}

      <div style={{ fontSize: 11, color: 'var(--fg3)', textAlign: 'center', marginTop: 10, lineHeight: 1.5 }}>
        {t('book_not_charged_full')} — {psy.name.split(' ').slice(-1)[0]} {t('book_confirms_full')}
      </div>
    </aside>
  );
}

Object.assign(window, { DetailScreen, BookingCard });
