// PracticeDetail.jsx — Full practice profile screen (#practice-detail)
// Reads tda_selected_practice from localStorage (set by DirectoryCard openProfile).
// Compliance: AB 3030, VPS methodology link, positive-only recognition, no star ratings.

const { useState, useEffect } = React;

const AB3030 = 'AI-assisted content is disclosed under California AB 3030. This is information, not a clinical diagnosis — confirm with a licensed dentist.';
const VPS_TOOLTIP = 'Positive-only recognition. Never paid placement. Methodology 2026.05';

const R = window.RECOGNITION;

/** Directory API may send vps as a number or per-axis score map — never render the map in JSX. */
function numericVpsScore(practice) {
  if (!practice) return null;
  const raw = practice.overall_score ?? practice.vps_score ?? practice.vps;
  if (typeof raw === 'number' && !Number.isNaN(raw)) return Math.round(raw);
  if (typeof raw === 'string' && /^\d+(\.\d+)?$/.test(raw.trim())) return Math.round(Number(raw));
  if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
    const vals = Object.values(raw).map(Number).filter((n) => !Number.isNaN(n));
    if (vals.length) return Math.round(Math.max(...vals));
  }
  return null;
}

/** Canonical badges: [[axisSlug, tierSlug], …] from directory / Supabase / demo seed. */
function normalizeBadges(practice) {
  if (!practice) return [];
  if (Array.isArray(practice.badges) && practice.badges.length) {
    return practice.badges.filter((b) => Array.isArray(b) && b[0] && b[1] && b[1] !== 'listed');
  }
  if (Array.isArray(practice.earned_axes) && practice.earned_axes.length) {
    return practice.earned_axes
      .filter((a) => a && a.axis && a.tier && a.tier !== 'listed')
      .map((a) => [a.axis, a.tier]);
  }
  return [];
}

function specialtyTags(practice) {
  if (Array.isArray(practice.specialties) && practice.specialties.length) {
    return practice.specialties.slice(0, 4).map((s) => s.label || s.subspecialty || s.specialty).filter(Boolean);
  }
  if (practice.specialty) return [practice.specialty];
  return ['General Dentistry'];
}

function VPSDonut({ score }) {
  const n = typeof score === 'number' && !Number.isNaN(score) ? Math.round(score) : null;
  const r = 44;
  const circ = 2 * Math.PI * r;
  const filled = n != null ? (n / 100) * circ : 0;
  const [shown, setShown] = useState(false);
  useEffect(() => { const t = setTimeout(() => setShown(true), 100); return () => clearTimeout(t); }, []);
  const dash = shown ? filled : 0;
  const gradId = 'vps-ring-grad';

  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>
      <div title={VPS_TOOLTIP} style={{ cursor: 'help' }}>
        <svg width={112} height={112} viewBox="0 0 112 112" aria-label={n != null ? `VPS score ${n} out of 100` : 'VPS score not yet published'}>
          <defs>
            <linearGradient id={gradId} x1="0%" y1="0%" x2="100%" y2="100%">
              <stop offset="0%" className="session-vps-ring-fill" />
              <stop offset="100%" className="session-vps-ring-fill-end" />
            </linearGradient>
          </defs>
          <circle cx={56} cy={56} r={r} fill="none" className="session-vps-ring-track" stroke="var(--line)" strokeWidth={10}/>
          <circle
            cx={56} cy={56} r={r} fill="none"
            stroke={`url(#${gradId})`} strokeWidth={10}
            strokeLinecap="round"
            strokeDasharray={`${dash} ${circ}`}
            strokeDashoffset={circ * 0.25}
            style={{ transition: 'stroke-dasharray 1.2s cubic-bezier(0.22,1,0.36,1)' }}
          />
          <text x={56} y={50} textAnchor="middle" dominantBaseline="middle"
            className="session-vps-score"
            style={{ fontSize: 22, fontWeight: 700 }}>{n != null ? n : '—'}</text>
          <text x={56} y={68} textAnchor="middle" dominantBaseline="middle"
            className="session-vps-label"
            style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.06em' }}>VPS</text>
        </svg>
      </div>
      <p className="t-fine" style={{ fontSize: 11, textAlign: 'center', maxWidth: 140, margin: 0, color: 'var(--mut)' }}>
        {VPS_TOOLTIP}
      </p>
      <a href="/methodology/" className="methodology-link" style={{ fontSize: 11 }}>
        Methodology 2026.05 →
      </a>
    </div>
  );
}

function RecognitionSection({ practice }) {
  const badges = normalizeBadges(practice);
  if (!badges.length) return null;

  const axisLabel = (slug) => (R && R.axisShort ? R.axisShort(slug) : slug);
  const tierLabel = (tier) => (R && R.tierLabel ? R.tierLabel(tier) : tier);

  return (
    <div>
      <p className="session-label" style={{ marginBottom: 8 }}>
        Earned Recognition · {badges.length} {badges.length === 1 ? 'area' : 'areas'}
      </p>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
        {badges.map(([axis, tier]) => (
          <span
            key={axis}
            className="badge badge-blue"
            style={{ fontSize: 12, padding: '6px 12px', borderRadius: 99 }}
            title={`${axisLabel(axis)} — ${tierLabel(tier)}`}
          >
            {axisLabel(axis)}
            <span style={{ opacity: 0.75, marginLeft: 6, fontWeight: 500 }}>{tierLabel(tier)}</span>
          </span>
        ))}
      </div>
      <p style={{ fontSize: 11, color: 'var(--mut)', marginTop: 12 }}>
        Positive-only recognition. Unearned axes are not shown. No paid placement as a quality signal.{' '}
        <a href="/methodology/" className="methodology-link">How we measure →</a>
      </p>
    </div>
  );
}

function InsurancePanel({ insurances }) {
  if (!insurances || !insurances.length) return (
    <p style={{ fontSize: 13, color: 'var(--mut)' }}>Insurance information not yet verified.</p>
  );
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
      {insurances.map((ins, i) => (
        <span key={i} className="badge badge-gray" style={{ fontSize: 12 }}>{ins}</span>
      ))}
    </div>
  );
}

function SimilarPracticeCard({ practice, go }) {
  return (
    <div
      className="card"
      style={{ cursor: 'pointer', display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 16px' }}
      onClick={() => {
        try { localStorage.setItem('tda_selected_practice', JSON.stringify(practice)); } catch (_) {}
        if (go) go('practice-detail');
      }}
      role="button"
      tabIndex={0}
      onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') { try { localStorage.setItem('tda_selected_practice', JSON.stringify(practice)); } catch (_) {} if (go) go('practice-detail'); } }}
    >
      <div>
        <div style={{ fontWeight: 600, fontSize: 14, color: 'var(--txt)' }}>{practice.name}</div>
        <div style={{ fontSize: 12, color: 'var(--mut)', marginTop: 2 }}>{practice.city || practice.address}</div>
      </div>
      <div style={{ textAlign: 'right' }}>
        <div className="session-stat-num" style={{ fontSize: 18 }}>{numericVpsScore(practice) ?? '—'}</div>
        <div className="session-muted" style={{ fontSize: 10 }}>VPS</div>
      </div>
    </div>
  );
}

function PracticeDetail({ go, state }) {
  const [practice, setPractice] = useState(null);
  const [similar, setSimilar] = useState([]);
  const [similarLoading, setSimilarLoading] = useState(false);
  const [similarErr, setSimilarErr] = useState(false);

  useEffect(() => {
    const fromState = state && state._selectedDentist;
    if (fromState) { setPractice(fromState); return; }
    try {
      const raw = localStorage.getItem('tda_selected_practice');
      if (raw) setPractice(JSON.parse(raw));
    } catch (_) {}
  }, [state]);

  useEffect(() => {
    if (!practice) return;
    let cancelled = false;
    setSimilarLoading(true);
    setSimilarErr(false);
    const zip = (practice.zip || practice.zip3 || '').toString().replace(/\D/g, '').slice(0, 5);
    const subspecialty = practice.specialties?.[0]?.subspecialty;
    const qs = new URLSearchParams();
    if (zip) qs.set('zip', zip);
    if (subspecialty) qs.set('subspecialty', subspecialty);
    qs.set('limit', '6');
    fetch(`/api/directory?${qs}`)
      .then((r) => r.json())
      .then((d) => {
        if (cancelled || !d?.results) return;
        const selfKey = practice.npi || practice.practice_id || practice.name;
        const pool = d.results
          .filter((p) => (p.npi || p.practice_id || p.name) !== selfKey)
          .slice(0, 3);
        setSimilar(pool.length ? pool : []);
      })
      .catch(() => { if (!cancelled) setSimilarErr(true); })
      .finally(() => { if (!cancelled) setSimilarLoading(false); });
    return () => { cancelled = true; };
  }, [practice]);

  if (!practice) {
    return (
      <div className="session-screen gap-screen animate-fade-in-up">
        <button type="button" className="btn btn-ghost btn-sm session-back" onClick={() => go?.('directory')} aria-label="Back to directory">
          ← Directory
        </button>
        {window.EmptyState ? (
          <EmptyState
            title="No practice selected"
            description="Browse verified practices in your area."
            onAction={() => go?.('directory')}
            actionLabel="Browse directory"
            variant="search"
          />
        ) : (
          <div className="disclaimer-banner">
            No practice selected. <button type="button" className="btn btn-ghost btn-sm" onClick={() => go?.('directory')}>Browse the directory →</button>
          </div>
        )}
      </div>
    );
  }

  const vps = numericVpsScore(practice);
  const insurances = practice.insurance || [];
  const languages = practice.languages || ['English'];
  const phone = practice.phone || practice.phone_number || null;
  const address = practice.address || practice.location || null;
  const accepting = practice.accepting !== false;
  const tags = specialtyTags(practice);
  const similarList = similar.length >= 1 ? similar : [];

  return (
    <div className="session-screen session-screen--sticky-cta gap-screen animate-fade-in-up">
      <button type="button" className="btn btn-ghost btn-sm session-back" onClick={() => go?.('directory')} aria-label="Back to directory">
        ← Directory
      </button>

      <p className="session-eyebrow t-eyebrow">
        VERIFIED · INDEPENDENT · NO PAID PLACEMENT
      </p>

      <div style={{ display: 'flex', gap: 20, alignItems: 'flex-start', marginBottom: 24, flexWrap: 'wrap' }}>
        <div style={{ flex: 1, minWidth: 200 }}>
          <h1 className="session-title">
            {practice.name}
          </h1>
          <p className="session-muted" style={{ fontSize: 14, margin: '0 0 8px' }}>
            {practice.city || practice.address || 'Location on file'}
          </p>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 8 }}>
            {tags.map((t) => (
              <span key={t} className="badge badge-gray" style={{ fontSize: 11 }}>{t}</span>
            ))}
          </div>
          {accepting !== undefined && (
            <span className={accepting ? 'badge badge-green' : 'badge badge-yellow'} style={{ display: 'inline-flex' }} aria-label={accepting ? 'Accepting new patients' : 'Waitlist only'}>
              <span aria-hidden="true">{accepting ? '✓' : '⏳'}</span>{' '}
              {accepting ? 'Accepting new patients' : 'Waitlist only'}
            </span>
          )}
        </div>
        <VPSDonut score={vps} />
      </div>

      {normalizeBadges(practice).length > 0 && (
        <div className="card" style={{ marginBottom: 16 }}>
          <RecognitionSection practice={practice} />
        </div>
      )}

      <div className="card" style={{ marginBottom: 16 }}>
        <p style={{ fontSize: 12, color: 'var(--mut)', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 8 }}>
          Insurance Accepted
        </p>
        <InsurancePanel insurances={insurances} />
      </div>

      {languages.length > 0 && (
        <div className="card" style={{ marginBottom: 16 }}>
          <p style={{ fontSize: 12, color: 'var(--mut)', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 8 }}>
            Languages Spoken
          </p>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
            {languages.map((l, i) => (
              <span key={i} className="badge badge-gray" style={{ fontSize: 12 }}>{l}</span>
            ))}
          </div>
        </div>
      )}

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: 12, marginBottom: 16 }}>
        <button
          type="button"
          className="card"
          style={{ textAlign: 'left', cursor: 'pointer', border: '1.5px solid var(--line)', background: 'var(--panel)' }}
          onClick={() => go?.('cost-estimate')}
        >
          <div style={{ fontSize: 20, marginBottom: 4 }}>💵</div>
          <div style={{ fontWeight: 600, fontSize: 14 }}>Cost Estimate</div>
          <div style={{ fontSize: 12, color: 'var(--mut)' }}>Transparent pricing with cited sources →</div>
        </button>
        <button
          type="button"
          className="card"
          style={{ textAlign: 'left', cursor: 'pointer', border: '1.5px solid var(--line)', background: 'var(--panel)' }}
          onClick={() => go?.('second-opinion')}
        >
          <div style={{ fontSize: 20, marginBottom: 4 }}>🔍</div>
          <div style={{ fontWeight: 600, fontSize: 14 }}>Second Opinion</div>
          <div style={{ fontSize: 12, color: 'var(--mut)' }}>
            Informational review — licensed dentist confirms (HITL)
          </div>
        </button>
      </div>

      {(similarLoading || similarErr || similarList.length > 0) && (
        <div style={{ marginBottom: 24 }}>
          <p className="session-label" style={{ marginBottom: 10 }}>
            Similar Practices
          </p>
          {similarLoading && window.Skeleton ? <Skeleton lines={3} height={16} /> : null}
          {similarErr && window.ErrorRetry ? (
            <ErrorRetry message="Could not load similar practices." onRetry={() => setPractice({ ...practice })} />
          ) : null}
          {!similarLoading && !similarErr && similarList.length > 0 && (
          <div className="session-stack session-stack--sm">
            {similarList.map((p, i) => (
              <SimilarPracticeCard key={p.npi || p.practice_id || i} practice={p} go={go} />
            ))}
          </div>
          )}
        </div>
      )}

      <div className="disclaimer-banner" style={{ marginBottom: 12 }}>{AB3030}</div>

      <p style={{ fontSize: 11, color: 'var(--mut)', textAlign: 'center' }}>
        TheDentist<em style={{ fontStyle: 'italic' }}>.ai</em> · Smile Mentors Inc. ·{' '}
        <a href="/methodology/" className="methodology-link" style={{ fontSize: 11 }}>Recognition methodology 2026.05</a>
      </p>

      {(phone || address) && (
        <div className="session-sticky-cta" role="region" aria-label="Contact actions">
          {phone && (
            <a href={`tel:${phone}`} className="btn btn-secondary" style={{ flex: '1 1 80px' }}>📞 {phone}</a>
          )}
          {address && (
            <a
              href={`https://maps.google.com/?q=${encodeURIComponent(address)}`}
              target="_blank" rel="noopener noreferrer"
              className="btn btn-secondary"
              style={{ flex: '1 1 100px', fontSize: 13 }}
            >
              📍 Directions
            </a>
          )}
          {typeof BookAppointmentCTA === 'function' ? (
            <div style={{ flex: '2 1 140px' }}>
              <BookAppointmentCTA dentist={practice} surface="practice-detail" label="Book via Trafft" size="md" />
            </div>
          ) : (
            <button type="button" className="btn btn-primary" style={{ flex: 2 }}
              onClick={() => { if (typeof window.openTrafftBooking === 'function') window.openTrafftBooking(practice, { surface: 'practice-detail' }); else go?.('forms'); }}>
              Book via Trafft
            </button>
          )}
        </div>
      )}
    </div>
  );
}

window.PracticeDetail = PracticeDetail;
