/* app-drug.jsx — 의약품 정보 탭
   drug_classes.json → 대분류→질환→약물분류→성분/상품명 계층 탐색
   성분명 클릭 → 하단 상세 드로어 (DrugPopup v2 디자인) */

// buildDrugIndex → src/data/drug-index.js (window.buildDrugIndex)

/* ── 추가 색상 토큰 (RX에 없는 blue 계열) ────── */
const DK = {
  blue:   '#1a4a7a',
  blueBg: '#e8f0fb',
  blueLn: '#b0c8ed',
};

const CARD = { w: 156 };
const PHOTO_RATIO = '16 / 10';

/* ── 검색 하이라이트 ─────────────────────────── */
function Hl({ text, q }) {
  if (!text) return text;
  if (!q) return text;
  const i = text.toLowerCase().indexOf(q.toLowerCase());
  if (i < 0) return text;
  return <>{text.slice(0, i)}<mark style={{ background: '#c8f2e8', color: RX.teal, borderRadius: 2, padding: '0 1px' }}>{text.slice(i, i + q.length)}</mark>{text.slice(i + q.length)}</>;
}

function FitText({ text, max = 11, min = 7, weight = 700, color = RX.ink, lines = 1 }) {
  const boxRef = React.useRef(null);
  const textRef = React.useRef(null);
  const [size, setSize] = React.useState(max);

  React.useLayoutEffect(() => {
    const box = boxRef.current;
    const node = textRef.current;
    if (!box || !node) return;

    const fit = () => {
      let next = max;
      node.style.fontSize = `${next}px`;
      const fits = () => {
        if (lines > 1) return node.scrollHeight <= box.clientHeight && node.scrollWidth <= box.clientWidth + 1;
        return node.scrollWidth <= box.clientWidth + 1;
      };
      while (next > min && !fits()) {
        next -= 0.5;
        node.style.fontSize = `${next}px`;
      }
      setSize(next);
    };

    fit();
    if (typeof ResizeObserver === 'undefined') return;
    const ro = new ResizeObserver(fit);
    ro.observe(box);
    return () => ro.disconnect();
  }, [text, max, min, lines]);

  return (
    <span ref={boxRef} style={{
      display: 'block', width: '100%', height: '100%', overflow: 'hidden',
      lineHeight: lines > 1 ? 1.15 : 1, color,
    }}>
      <span ref={textRef} style={{
        display: lines > 1 ? '-webkit-box' : 'block',
        WebkitLineClamp: lines > 1 ? lines : undefined,
        WebkitBoxOrient: lines > 1 ? 'vertical' : undefined,
        whiteSpace: lines > 1 ? 'normal' : 'nowrap',
        overflow: 'hidden', fontSize: size, fontWeight: weight,
      }}>{text}</span>
    </span>
  );
}

function cleanText(text) {
  return (text || '').replace(/&nbsp;/g, ' ').trim();
}

function isComboGeneric(generic) {
  return (generic || '').includes('+');
}

function genericParts(generic) {
  return (generic || '').split('+').map(s => s.trim()).filter(Boolean);
}

function strengthDoseLabel(strength, combo) {
  if (!combo) return strength?.dose || '용량';
  const m = (strength?.official_name || '').match(/(\d+(?:\.\d+)?(?:\/\d+(?:\.\d+)?)+)\s*(?:mg|밀리그램)/i);
  if (m) return `${m[1]}mg`;
  return strength?.dose || '용량';
}

function usageSummaryKey(strength, brand) {
  if (!strength?.item_seq) return '';
  return `${strength.item_seq}|${brand?.brand || brand?.name || ''}|${brand?.generic || ''}|${strength.dose || ''}`;
}

const STORAGE_BASE =
  'https://firebasestorage.googleapis.com/v0/b/pharmacist-a4e7f.firebasestorage.app/o/';

function imageSrc(localPath) {
  if (!localPath) return null;
  if (/^(https?:|data:|\/)/.test(localPath)) return localPath;
  const path = localPath.replace(/^data\//, '');   // pill_images/X.jpg
  return STORAGE_BASE + encodeURIComponent(path) + '?alt=media';
}

function InfoBox({ text, empty = '준비 중입니다.' }) {
  const body = cleanText(text);
  return (
    <div style={{
      background: RX.shell, border: `1px solid ${RX.lineSoft}`, borderRadius: 10,
      padding: '10px 12px', fontSize: 12.5, fontWeight: 600, lineHeight: 1.75,
      color: body ? RX.ink : RX.faint, fontStyle: body ? 'normal' : 'italic',
      whiteSpace: 'pre-line', wordBreak: 'keep-all',
    }}>{body || empty}</div>
  );
}

function GeneralPrinciplePanel({ principle, onClose }) {
  if (!principle) return null;
  return (
    <div style={{
      margin: '8px 12px 0',
      padding: 12,
      border: `1px solid ${RX.tealLine}`,
      borderRadius: 8,
      background: RX.paper,
      boxShadow: '0 4px 14px rgba(16, 42, 35, 0.08)',
      flexShrink: 0,
      maxHeight: '55vh',
      overflowY: 'auto',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
        <strong style={{ fontSize: 12.5, color: RX.teal }}>{principle.title}</strong>
        <button onClick={onClose} style={{
          marginLeft: 'auto',
          border: `1px solid ${RX.line}`,
          background: RX.shell,
          color: RX.faint,
          borderRadius: 6,
          padding: '3px 7px',
          fontSize: 10.5,
          fontWeight: 800,
          cursor: 'pointer',
        }}>닫기</button>
      </div>
      <section style={{ marginBottom: 10 }}>
        <div style={{ fontSize: 11, fontWeight: 900, color: RX.teal, marginBottom: 5 }}>요약본</div>
        <div style={{ fontSize: 12, lineHeight: 1.6, color: RX.ink, wordBreak: 'keep-all' }}>
          {principle.summary}
        </div>
      </section>
      <section style={{ borderTop: `1px solid ${RX.lineSoft}`, paddingTop: 10 }}>
        <div style={{ fontSize: 11, fontWeight: 900, color: RX.faint, marginBottom: 5 }}>전문</div>
        <div style={{ fontSize: 11.5, lineHeight: 1.65, color: RX.muted, whiteSpace: 'pre-line', wordBreak: 'keep-all' }}>
          {principle.full_text}
        </div>
      </section>
    </div>
  );
}

function targetMatchesGeneralPrinciple(target, major, disease, classNames) {
  if (!target) return false;
  if (target.major && target.major !== major) return false;
  if (target.disease && target.disease !== disease) return false;
  if (target.drug_class && !classNames.includes(target.drug_class)) return false;
  return Boolean(target.major || target.disease || target.drug_class);
}

const coverageStyles = {
  covered: { bg: '#e6f4ee', ln: '#9ed6bd', tx: '#157347' },
  not_covered: { bg: RX.roseBg, ln: '#e0aab8', tx: RX.rose },
  unknown: { bg: RX.shell, ln: RX.lineSoft, tx: RX.faint },
};

function UsageSummaryBlock({ summary }) {
  if (!summary || !Array.isArray(summary.uses) || summary.uses.length === 0) return null;
  return (
    <div style={{
      marginBottom: 12, padding: '11px 12px', border: `1px solid ${RX.lineSoft}`,
      borderRadius: 10, background: RX.paper,
    }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 7, flexWrap: 'wrap', marginBottom: 9 }}>
        <span style={{ fontSize: 10.5, fontWeight: 800, color: RX.teal, letterSpacing: 0 }}>요약</span>
        <span style={{ fontSize: 10.5, fontWeight: 600, color: RX.faint, lineHeight: 1.4 }}>
          초록색은 급여인정, 붉은색은 본인부담, 회색은 아직 작업중인 내용입니다.
        </span>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
        {summary.uses.map((use) => {
          const s = coverageStyles[use.coverage] || coverageStyles.unknown;
          const isOffLabelUse = (use.coverage_label || '').toLowerCase().includes('off-label')
            || (Array.isArray(use.sources) && use.sources.includes('insurance') && !use.sources.includes('mfds'));
          return (
            <div key={use.disease} style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}>
              <span style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 2, flexShrink: 0 }}>
                <span title={use.coverage_label} style={{
                  display: 'inline-block', padding: '3px 8px', borderRadius: 99,
                  background: s.bg, border: `1px solid ${s.ln}`, color: s.tx,
                  fontSize: 10.5, fontWeight: 800, lineHeight: 1.1,
                }}>{use.disease}</span>
                {isOffLabelUse && (
                  <span style={{
                    fontSize: 7.5, fontWeight: 800, color: s.tx,
                    lineHeight: 1, opacity: 0.82, whiteSpace: 'nowrap', paddingLeft: 3,
                  }}>Off-label</span>
                )}
              </span>
              <div style={{ minWidth: 0 }}>
                <div style={{ fontSize: 12, fontWeight: 650, color: RX.ink, lineHeight: 1.5, wordBreak: 'keep-all' }}>{use.description}</div>
                <div style={{ fontSize: 11.5, fontWeight: 600, color: RX.sub, lineHeight: 1.5, marginTop: 2, wordBreak: 'keep-all' }}>{use.dose_usage}</div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function CrossRefsBlock({ refs }) {
  if (!Array.isArray(refs) || refs.length === 0) return null;
  const visibleRefs = refs.filter(ref => ref && ref.disease);
  if (visibleRefs.length === 0) return null;

  return (
    <div style={{
      marginBottom: 12,
      padding: '11px 12px',
      border: `1px solid ${RX.tealLine}`,
      borderRadius: 10,
      background: RX.tealTint,
    }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 7, flexWrap: 'wrap', marginBottom: 9 }}>
        <span style={{ fontSize: 10.5, fontWeight: 800, color: RX.teal, letterSpacing: 0 }}>다른 적응증</span>
        <span style={{ fontSize: 10.5, fontWeight: 600, color: RX.faint, lineHeight: 1.4 }}>
          같은 성분이 다른 질환 처방에서도 쓰이는 경우입니다.
        </span>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
        {visibleRefs.map((ref, i) => (
          <div key={`${ref.major || 'M'}-${ref.disease}-${ref.drug_class || i}`} style={{
            display: 'flex',
            alignItems: 'flex-start',
            gap: 8,
          }}>
            <span style={{
              display: 'inline-block',
              padding: '3px 8px',
              borderRadius: 99,
              background: RX.paper,
              border: `1px solid ${RX.tealLine}`,
              color: RX.teal,
              fontSize: 10.5,
              fontWeight: 800,
              lineHeight: 1.1,
              flexShrink: 0,
            }}>{ref.major || '기타'}</span>
            <div style={{ minWidth: 0 }}>
              <div style={{ fontSize: 12, fontWeight: 750, color: RX.ink, lineHeight: 1.45, wordBreak: 'keep-all' }}>
                {ref.disease}
              </div>
              {(ref.description || ref.interpretation || ref.drug_class) && (
                <div style={{ fontSize: 11.5, fontWeight: 600, color: RX.sub, lineHeight: 1.55, marginTop: 2, wordBreak: 'keep-all' }}>
                  {ref.description || ref.interpretation || ref.drug_class}
                </div>
              )}
            </div>
          </div>
        ))}
      </div>
      <div style={{ fontSize: 10.5, color: RX.faint, fontWeight: 600, lineHeight: 1.45, marginTop: 9, wordBreak: 'keep-all' }}>
        이 정보는 감별 힌트이며, 단독으로 질환을 확정하지 않습니다.
      </div>
    </div>
  );
}

/* ── 약물 사진 (gray fallback) ───────────────── */
function DrugPhoto({ src, onClick }) {
  const [err, setErr] = React.useState(false);
  const base = {
    width: '100%', aspectRatio: PHOTO_RATIO, borderRadius: 10, overflow: 'hidden',
    cursor: onClick ? 'pointer' : 'default', flexShrink: 0,
    border: `1px solid ${RX.lineSoft}`,
  };
  if (!src || err) {
    return (
      <div style={{ ...base, background: '#e0e4e0', display: 'flex', alignItems: 'center', justifyContent: 'center' }} onClick={onClick}>
        <span style={{ fontSize: 10, color: RX.faint, fontWeight: 600 }}>이미지 없음</span>
      </div>
    );
  }
  return (
    <div style={base} onClick={onClick}>
      <img src={src} onError={() => setErr(true)}
        style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block', background: '#f6f8f6' }} />
    </div>
  );
}


/* ── 성분 카드 (2열 그리드 내부) ─────────────── */
function GenericCard({ generic, brands, query, onOpenDetail }) {
  const [activeBrand, setActiveBrand] = React.useState(0);
  const [activeStrength, setActiveStrength] = React.useState(0);
  const combo = isComboGeneric(generic);
  const parts = genericParts(generic);
  const brand = brands[activeBrand] || brands[0] || {};
  const strengths = Array.isArray(brand.strengths) ? brand.strengths : [];
  const strength = strengths[activeStrength] || strengths[0] || {};
  return (
    <div style={{
      border: `1px solid ${RX.lineSoft}`, borderRadius: 10,
      padding: '8px', background: RX.paper,
      display: 'flex', flexDirection: 'column', gap: 6,
      width: CARD.w,
      overflow: 'hidden', flexShrink: 0,
    }}>
      {/* 성분명 */}
      <div style={{
        height: combo ? parts.length * 15 + Math.max(0, parts.length - 1) : 15, overflow: 'hidden',
      }}>
        {combo ? (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 1, height: '100%' }}>
            {parts.map((part) => (
              <div key={part} style={{ height: 15, minHeight: 0 }}>
                <FitText text={part} max={10.5} min={6.5} weight={800} color={RX.ink} />
              </div>
            ))}
          </div>
        ) : (
          <FitText text={generic} max={11.5} min={7.5} weight={800} color={RX.ink} lines={2} />
        )}
      </div>

      {/* 브랜드 칩 */}
      <div style={{ display: 'flex', gap: 4, overflow: 'hidden', flexShrink: 0, height: combo ? 23 : 21, alignItems: 'center' }}>
        {brands.map((b, i) => (
          <button key={b.name} onClick={() => { setActiveBrand(i); setActiveStrength(0); }} style={{
            padding: '3px 7px', borderRadius: 8, lineHeight: 1,
            border: `1.5px solid ${i === activeBrand ? RX.tealLine : RX.lineSoft}`,
            background: i === activeBrand ? RX.tealTint : RX.shell,
            color: i === activeBrand ? RX.teal : RX.sub,
            fontSize: 11, fontWeight: 700, cursor: 'pointer', fontFamily: 'inherit',
            minWidth: 0, maxWidth: 70, overflow: 'hidden', whiteSpace: 'nowrap',
            flex: '0 1 auto',
          }}>
            <FitText text={b.name} max={11} min={7} weight={700} color={i === activeBrand ? RX.teal : RX.sub} />
          </button>
        ))}
      </div>

      {/* 약물 사진 — 클릭 시 세부정보 열기 */}
      <DrugPhoto src={imageSrc(strength.image_local)} onClick={() => onOpenDetail(activeBrand, activeStrength)} />
      {strengths.length > 0 && (
        <div style={{
          display: 'flex', flexDirection: combo ? 'column' : 'row', gap: 3,
          overflow: 'hidden', flexShrink: 0,
        }}>
          {strengths.map((s, i) => (
            <button key={`${s.item_seq || s.dose || i}`} onClick={() => setActiveStrength(i)} style={{
              flex: combo ? '0 0 auto' : '1 1 0', minWidth: 0, width: combo ? '100%' : undefined,
              padding: '3px 2px', borderRadius: 7, lineHeight: 1,
              border: `1px solid ${i === activeStrength ? RX.tealLine : RX.lineSoft}`,
              background: i === activeStrength ? RX.tealTint : RX.shell,
              color: i === activeStrength ? RX.teal : RX.sub,
              fontSize: 10, fontWeight: 800, cursor: 'pointer', fontFamily: 'inherit',
              overflow: 'hidden', whiteSpace: 'nowrap',
            }}><FitText text={strengthDoseLabel(s, combo)} max={10} min={6.5} weight={800} color={i === activeStrength ? RX.teal : RX.sub} /></button>
          ))}
        </div>
      )}
    </div>
  );
}

/* ── 약물 분류 카드 ──────────────────────────── */
function DrugClassCard({ className, drugs, query, defaultOpen, onSelectDrug }) {
  const [open, setOpen] = React.useState(defaultOpen || false);
  React.useEffect(() => { if (query) setOpen(true); }, [query]);

  // 제네릭 그룹화
  const grouped = {};
  for (const d of drugs) {
    if (!grouped[d.generic]) grouped[d.generic] = { generic: d.generic, brands: [] };
    let brand = grouped[d.generic].brands.find(b => b.name === d.brand);
    if (!brand) {
      brand = { ...d, name: d.brand };
      grouped[d.generic].brands.push(brand);
    } else if ((!brand.strengths || brand.strengths.length === 0) && d.strengths && d.strengths.length > 0) {
      Object.assign(brand, d, { name: d.brand });
    }
  }
  const groups = Object.values(grouped);

  const matchesQuery = (g) => {
    if (!query) return true;
    const q = query.toLowerCase();
    return (g.generic || '').toLowerCase().includes(q)
      || g.brands.some(b => (b.name || '').toLowerCase().includes(q));
  };
  const visible = groups.filter(matchesQuery);
  if (query && visible.length === 0) return null;

  return (
    <div style={{ borderRadius: 10, border: `1px solid ${RX.line}`, overflow: 'hidden', background: RX.paper, flexShrink: 0 }}>
      {/* 분류 헤더 */}
      <button onClick={() => setOpen(o => !o)} style={{
        width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '9px 12px', background: open ? RX.tealTint : RX.paper,
        border: 'none', cursor: 'pointer', fontFamily: 'inherit', textAlign: 'left',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
          <span style={{ fontSize: 11.5, fontWeight: 800, color: open ? RX.teal : RX.ink }}>
            <Hl text={className} q={query} />
          </span>
          <span style={{
            fontSize: 10, fontWeight: 700,
            color: open ? RX.teal : RX.faint,
            background: open ? 'rgba(26,108,91,0.12)' : RX.shell,
            borderRadius: 99, padding: '1px 7px',
          }}>{groups.length}성분</span>
        </div>
        <svg width="12" height="12" viewBox="0 0 12 12" fill="none"
          style={{ transition: 'transform .18s', transform: open ? 'rotate(180deg)' : 'rotate(0deg)', flexShrink: 0 }}>
          <path d="M2 4l4 4 4-4" stroke={open ? RX.teal : RX.faint} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
      </button>

      {/* 성분 2열 그리드 */}
      {open && (
        <div style={{
          borderTop: `1px solid ${RX.tealLine}`,
          borderBottom: `1px solid ${RX.lineSoft}`,
          padding: '12px 12px 14px',
        }}>
          <div style={{
            display: 'grid',
            gridTemplateColumns: `repeat(auto-fill, ${CARD.w}px)`,
            gap: 8,
            justifyContent: 'start',
            alignItems: 'start',
          }}>
            {visible.map((g) => (
              <GenericCard
                key={g.generic}
                generic={g.generic}
                brands={g.brands}
                query={query}
                onOpenDetail={(brandIdx, strengthIdx) => onSelectDrug({ ...g, activeBrandIdx: brandIdx, activeStrengthIdx: strengthIdx, drugClass: className })}
              />
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

/* ── 성분 세부정보 바텀시트 ─────────────────── */
function DrugDetailSheet({ drug, usageSummary, onClose }) {
  const open = !!drug;
  const [activeBrand, setActiveBrand] = React.useState(0);
  const [activeStrength, setActiveStrength] = React.useState(0);
  const [memo, setMemo] = React.useState('');
  const combo = isComboGeneric(drug?.generic);

  // drug 변경 시 activeBrand 초기화
  React.useEffect(() => {
    if (drug) {
      setActiveBrand(drug.activeBrandIdx || 0);
      setActiveStrength(drug.activeStrengthIdx || 0);
    }
  }, [drug]);

  const brands = drug?.brands || [];
  const brand = brands[activeBrand] || brands[0] || {};
  const strengths = Array.isArray(brand.strengths) ? brand.strengths : [];
  const strength = strengths[activeStrength] || strengths[0] || {};
  const usage = usageSummary?.[usageSummaryKey(strength, brand)] || usageSummary?.[strength.item_seq];

  return (
    <>
      {/* 딤 */}
      {open && (
        <div onClick={onClose} style={{
          position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.3)',
          zIndex: 70, backdropFilter: 'blur(1px)',
        }} />
      )}

      {/* 시트 */}
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: 71,
        background: RX.paper, borderRadius: '18px 18px 0 0',
        boxShadow: '0 -6px 28px rgba(20,40,34,0.18)',
        transform: open ? 'translateY(0)' : 'translateY(100%)',
        transition: 'transform .28s cubic-bezier(.4,0,.2,1)',
        maxHeight: '82%', display: 'flex', flexDirection: 'column',
      }}>

        {/* ── tealTint 헤더 ── */}
        <div style={{
          background: RX.tealTint,
          borderBottom: `1px solid ${RX.tealLine}`,
          flexShrink: 0,
        }}>
          {/* 핸들 */}
          <div style={{ display: 'flex', justifyContent: 'center', padding: '12px 0 8px' }}>
            <div style={{ width: 38, height: 4, borderRadius: 99, background: RX.tealLine }} />
          </div>

          {/* 목록으로 | disease·class 중앙 | 빈칸 */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr auto 1fr', alignItems: 'center', padding: '0 18px 10px' }}>
            <div>
              <button onClick={onClose} style={{
                display: 'flex', alignItems: 'center', gap: 4, color: RX.teal,
                background: 'none', border: 'none', cursor: 'pointer', fontFamily: 'inherit',
              }}>
                <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
                  <path d="M10 3L5 8l5 5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                <span style={{ fontSize: 12, fontWeight: 700 }}>목록으로</span>
              </button>
            </div>
            <span style={{ fontSize: 10, fontWeight: 700, color: RX.teal, letterSpacing: 0, whiteSpace: 'nowrap' }}>
              {drug?.disease && `${drug.disease} · `}{drug?.drugClass}
            </span>
            <div />
          </div>

          {/* 성분명 */}
          <div style={{ fontSize: combo ? 16 : 19, fontWeight: 800, color: RX.ink, padding: '0 18px 10px', lineHeight: 1.25 }}>
            {combo ? genericParts(drug?.generic).map(part => <div key={part}>{part}</div>) : drug?.generic}
          </div>

          {/* 상품명 라벨 + 칩 */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '0 18px 14px', flexWrap: 'wrap' }}>
            <span style={{ fontSize: 10, fontWeight: 700, color: RX.teal, letterSpacing: 0, flexShrink: 0 }}>상품명</span>
            <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap' }}>
              {brands.map((b, i) => (
                <button key={b.name} onClick={() => { setActiveBrand(i); setActiveStrength(0); }} style={{
                  padding: '5px 13px', borderRadius: 8, lineHeight: 1,
                  border: `1.5px solid ${i === activeBrand ? RX.tealLine : RX.lineSoft}`,
                  background: i === activeBrand ? RX.tealTint : RX.shell,
                  color: i === activeBrand ? RX.teal : RX.sub,
                  fontSize: 13, fontWeight: 700, cursor: 'pointer', fontFamily: 'inherit',
                  transition: 'all .1s',
                }}>{b.name}</button>
              ))}
            </div>
          </div>

          {strengths.length > 0 && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '0 18px 14px', flexWrap: 'wrap' }}>
              <span style={{ fontSize: 10, fontWeight: 700, color: RX.teal, letterSpacing: 0, flexShrink: 0 }}>용량</span>
              <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap' }}>
                {strengths.map((s, i) => (
                  <button key={`${s.item_seq || s.dose || i}`} onClick={() => setActiveStrength(i)} style={{
                    padding: '5px 10px', borderRadius: 8, lineHeight: 1,
                    border: `1.5px solid ${i === activeStrength ? RX.tealLine : RX.lineSoft}`,
                    background: i === activeStrength ? RX.paper : RX.shell,
                    color: i === activeStrength ? RX.teal : RX.sub,
                    fontSize: 12, fontWeight: 800, cursor: 'pointer', fontFamily: 'inherit',
                  }}>{strengthDoseLabel(s, combo) || '용량 미상'}</button>
                ))}
              </div>
            </div>
          )}
        </div>

        {/* ── 본문 스크롤 영역 ── */}
        <div className="sc" style={{ flex: 1, overflowY: 'auto', padding: '0 18px 28px' }}>

          {/* 약물 사진 */}
          <div style={{ margin: '16px auto', width: '100%', maxWidth: 256 }}>
            <DrugPhoto src={imageSrc(strength.image_local)} />
          </div>

          {(strength.official_name || strength.entp_name || brand.route) && (
            <div style={{
              marginBottom: 12, padding: '9px 11px', border: `1px solid ${RX.lineSoft}`,
              borderRadius: 10, background: RX.paper, color: RX.sub, fontSize: 11.5,
              fontWeight: 650, lineHeight: 1.55,
            }}>
              {strength.official_name && <div style={{ color: RX.ink, fontWeight: 800 }}>{strength.official_name}</div>}
              {(strength.entp_name || brand.route) && (
                <div>{[strength.entp_name, brand.route].filter(Boolean).join(' · ')}</div>
              )}
            </div>
          )}

          <UsageSummaryBlock summary={usage} />
          <CrossRefsBlock refs={brand.cross_refs} />

          {/* 용법용량 */}
          <div style={{ marginBottom: 12 }}>
            <div style={{ fontSize: 10.5, fontWeight: 700, color: RX.teal, letterSpacing: 0, marginBottom: 6 }}>용법용량</div>
            <InfoBox text={strength.useMethod} />
          </div>

          {/* 효능효과 */}
          <div style={{ marginBottom: 12 }}>
            <div style={{ fontSize: 10.5, fontWeight: 700, color: RX.teal, letterSpacing: 0, marginBottom: 6 }}>효능효과</div>
            <InfoBox text={strength.efcy} />
          </div>

          {/* 기타 메모 */}
          <div style={{ marginBottom: 16 }}>
            <div style={{ fontSize: 10.5, fontWeight: 700, color: RX.teal, letterSpacing: 0, marginBottom: 6 }}>기타 메모</div>
            <textarea
              value={memo} onChange={e => setMemo(e.target.value)}
              placeholder="약사 메모를 입력하세요…" rows={3}
              style={{
                width: '100%', background: RX.shell, border: `1px solid ${RX.lineSoft}`,
                borderRadius: 10, padding: '10px 12px', fontSize: 12.5, fontWeight: 600,
                lineHeight: 1.75, color: RX.ink, fontFamily: 'inherit', resize: 'none', outline: 'none',
                boxSizing: 'border-box',
              }}
            />
          </div>

          {/* 구분선 */}
          <div style={{ height: 1, background: RX.lineSoft, marginBottom: 14 }} />


        </div>

        <style>{`.sc::-webkit-scrollbar{width:3px}.sc::-webkit-scrollbar-thumb{background:#d9dcd8;border-radius:99px}.sc{scrollbar-width:thin;scrollbar-color:#d9dcd8 transparent}`}</style>
      </div>
    </>
  );
}

/* ── 진료과 코드 → 표시 라벨 ─────────────────── */
const MAJOR_LABEL_MAP = {
  CV: 'CV 심혈관내과', AI: 'AI 면역·알레르기내과', DEN: 'DEN 치과',
  DERM: 'DERM 피부과', ED: 'ED 내분비내과', ENT: 'ENT 이비인후과',
  GI: 'GI 소화기내과', IF: 'IF 감염내과', NH: 'NH 신장내과',
  NP: 'NP 정신건강의학과', NU: 'NU 신경과', OBGY: 'OBGY 산부인과',
  OS: 'OS 정형/신경외과', PM: 'PM 호흡기내과', RH: 'RH 류마티스내과',
  URO: 'URO 비뇨기내과', EYE: 'EYE 안과',
};
const MAJOR_ORDER = ['CV', 'ED', 'PM', 'GI', 'IF', 'NH', 'RH', 'AI', 'ENT', 'DERM', 'URO', 'OBGY', 'NP', 'NU', 'OS', 'DEN'];

/* ── 메인 약물 정보 탭 ─────────────────────────── */
function AppDrug() {
  const { plan } = React.useContext(window.AuthContext || {});
  const [drugIndex, setDrugIndex] = React.useState(null);
  const [usageSummary, setUsageSummary] = React.useState({});
  const [generalPrinciples, setGeneralPrinciples] = React.useState([]);
  const [major, setMajor] = React.useState('CV');
  const [disease, setDisease] = React.useState(null);
  const [query, setQuery] = React.useState('');
  const [activePrincipleId, setActivePrincipleId] = React.useState(null);
  const [selectedDrug, setSelectedDrug] = React.useState(null); // { generic, brands, drugClass, disease, activeBrandIdx }
  const contentRef = React.useRef(null);

  const isUnlocked = window.isUnlocked(plan);

  React.useEffect(() => {
    if (!isUnlocked && major !== 'CV') {
      setMajor('CV');
      if (drugIndex) setDisease(Object.keys(drugIndex['CV'] || {})[0] || null);
    }
  }, [isUnlocked, major]);

  React.useEffect(() => {
    fetch('data/drug_classes.json')
      .then(r => r.json())
      .then(data => {
        const idx = window.buildDrugIndex(data);
        setDrugIndex(idx);
        setDisease(Object.keys(idx['CV'] || {})[0] || null);
      });
    fetch('data/drug_usage_summary.json')
      .then(r => r.ok ? r.json() : {})
      .then(data => setUsageSummary(data || {}))
      .catch(() => setUsageSummary({}));
    fetch('data/drug_general_principles.json')
      .then(r => r.ok ? r.json() : [])
      .then(data => setGeneralPrinciples(Array.isArray(data) ? data : []))
      .catch(() => setGeneralPrinciples([]));
  }, []);

  const allMajors = React.useMemo(() => {
    if (!drugIndex) return [];
    const keys = Object.keys(drugIndex);
    const ordered = MAJOR_ORDER.filter(k => keys.includes(k));
    const rest = keys.filter(k => !MAJOR_ORDER.includes(k)).sort();
    return [...ordered, ...rest];
  }, [drugIndex]);

  const handleMajorChange = (m) => {
    if (!isUnlocked && m !== 'CV') return;
    setMajor(m);
    const first = drugIndex ? Object.keys(drugIndex[m] || {})[0] || null : null;
    setDisease(first);
    setQuery('');
    setActivePrincipleId(null);
    if (contentRef.current) contentRef.current.scrollTop = 0;
  };

  const handleDiseaseChange = (d) => {
    setDisease(d);
    setQuery('');
    setActivePrincipleId(null);
    if (contentRef.current) contentRef.current.scrollTop = 0;
  };

  const diseases = drugIndex ? Object.keys(drugIndex[major] || {}) : [];
  const classes = (drugIndex && disease) ? Object.entries(drugIndex[major]?.[disease] || {}) : [];

  const filteredClasses = query
    ? classes.filter(([cls, drugs]) => {
      const q = query.toLowerCase();
      return cls.toLowerCase().includes(q)
        || drugs.some(d => d.generic.toLowerCase().includes(q) || d.brand.toLowerCase().includes(q));
    })
    : classes;

  const totalCount = classes.reduce((s, [, d]) => {
    const generics = [...new Set(d.map(x => x.generic))];
    return s + generics.length;
  }, 0);
  const matchedGeneralPrinciples = React.useMemo(() => {
    const classNames = filteredClasses.map(([cls]) => cls);
    return generalPrinciples.filter(principle =>
      Array.isArray(principle.targets)
      && principle.targets.some(target => targetMatchesGeneralPrinciple(target, major, disease, classNames))
    );
  }, [generalPrinciples, major, disease, filteredClasses]);
  const activeGeneralPrinciple = matchedGeneralPrinciples.find(p => p.id === activePrincipleId) || null;

  if (!drugIndex) return (
    <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', color: RX.faint, fontSize: 13, gap: 8 }}>
      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" style={{ animation: 'spin 1s linear infinite' }}>
        <circle cx="12" cy="12" r="9" stroke={RX.line} strokeWidth="2" />
        <path d="M12 3a9 9 0 019 9" stroke={RX.teal} strokeWidth="2.2" strokeLinecap="round" />
      </svg>
      불러오는 중…
      <style>{`@keyframes spin{to{transform:rotate(360deg)}}`}</style>
    </div>
  );

  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', position: 'relative' }}>

      {/* ── 셀렉터 바 ── */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, padding: '11px 12px', background: RX.shell, borderBottom: `1px solid ${RX.line}`, flexShrink: 0 }}>

        {/* 진료과 드롭다운 */}
        <Dropdown
          value={major}
          items={allMajors.map(m => {
            const locked = !isUnlocked && m !== 'CV';
            return {
              value: m,
              label: (MAJOR_LABEL_MAP[m] || m) + (locked ? ' 🔒' : ''),
              hint: locked ? null : (drugIndex ? Object.keys(drugIndex[m] || {}).length + '질환' : null),
            };
          })}
          onChange={v => {
            const locked = !isUnlocked && v !== 'CV';
            if (!locked) handleMajorChange(v);
          }}
        />

        {/* 질환 드롭다운 */}
        <Dropdown
          value={disease}
          items={diseases.map(d => ({ value: d, label: d }))}
          onChange={handleDiseaseChange}
        />

        {/* 검색 */}
        <div style={{ position: 'relative' }}>
          <svg style={{ position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)' }}
            width="13" height="13" viewBox="0 0 16 16" fill="none">
            <circle cx="7" cy="7" r="5" stroke={RX.faint} strokeWidth="1.5" />
            <path d="M11 11l3 3" stroke={RX.faint} strokeWidth="1.5" strokeLinecap="round" />
          </svg>
          <input type="text" value={query} onChange={e => setQuery(e.target.value)}
            placeholder="성분명·상품명 검색…"
            style={{
              width: '100%', padding: '8px 10px 8px 30px', fontSize: 12.5, fontFamily: 'inherit',
              color: RX.ink, border: `1px solid ${RX.line}`, borderRadius: 8,
              background: RX.paper, outline: 'none', boxSizing: 'border-box',
            }}
          />
          {query && (
            <button onClick={() => setQuery('')} style={{
              position: 'absolute', right: 9, top: '50%', transform: 'translateY(-50%)',
              background: 'none', border: 'none', cursor: 'pointer', fontSize: 14, color: RX.faint, lineHeight: 1, padding: 0,
            }}>×</button>
          )}
        </div>
      </div>

      {/* 요약 배너 */}
      {disease && (
        <div style={{ padding: '6px 12px', background: RX.tealTint, borderBottom: `1px solid ${RX.tealLine}`, flexShrink: 0, display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
          <span style={{ fontSize: 12, fontWeight: 800, color: RX.teal }}>{disease}</span>
          <span style={{ fontSize: 10.5, color: RX.teal, fontWeight: 600 }}>
            {filteredClasses.length}분류 · {query ? '검색 결과' : `${totalCount}성분`}
          </span>
          <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
            {matchedGeneralPrinciples.map(principle => {
              const active = activePrincipleId === principle.id;
              return (
                <button key={principle.id} onClick={() => setActivePrincipleId(active ? null : principle.id)} style={{
                  border: `1px solid ${RX.tealLine}`,
                  background: active ? RX.teal : RX.paper,
                  color: active ? '#fff' : RX.teal,
                  borderRadius: 6,
                  padding: '4px 8px',
                  fontSize: 10.5,
                  fontWeight: 900,
                  cursor: 'pointer',
                }}>{principle.button_label}</button>
              );
            })}
            {query && (
              <span style={{ fontSize: 10, fontWeight: 700, color: RX.teal, background: 'rgba(26,108,91,0.15)', borderRadius: 99, padding: '2px 8px' }}>
                "{query}"
              </span>
            )}
          </div>
        </div>
      )}
      {matchedGeneralPrinciples.length > 0 && (
        <GeneralPrinciplePanel
          principle={activeGeneralPrinciple}
          onClose={() => setActivePrincipleId(null)}
        />
      )}

      {/* 카드 목록 */}
      <div ref={contentRef} style={{ flex: 1, overflowY: 'auto', padding: '10px 12px 20px', display: 'flex', flexDirection: 'column', gap: 8 }}>
        {filteredClasses.length === 0 ? (
          <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 8, color: RX.faint, paddingTop: 40 }}>
            <svg width="32" height="32" viewBox="0 0 32 32" fill="none"><circle cx="15" cy="15" r="11" stroke={RX.line} strokeWidth="2" /><path d="M24 24l5 5" stroke={RX.line} strokeWidth="2" strokeLinecap="round" /></svg>
            <span style={{ fontSize: 12 }}>"{query}" 결과 없음</span>
          </div>
        ) : (
          filteredClasses.map(([cls, drugs]) => (
            <DrugClassCard
              key={cls}
              className={cls}
              drugs={drugs}
              query={query}
              defaultOpen={filteredClasses.length <= 3}
              onSelectDrug={(g) => setSelectedDrug({ ...g, disease })}
            />
          ))
        )}
      </div>

      {/* 성분 세부정보 시트 */}
      <DrugDetailSheet
        drug={selectedDrug}
        usageSummary={usageSummary}
        onClose={() => setSelectedDrug(null)}
      />
    </div>
  );
}

window.AppDrug = AppDrug;
