// 그란데 독서타임 — 도끼책 원정대 (소개·도끼꾼 모집 랜딩)
// 전시장 모드: 책/일정은 정적 config. 신청만 Apps Script 웹앱(+시트)으로 기기 무관 연동.
//  - 신청 제출/조회는 JSONP GET (정적 사이트 ↔ Apps Script 크로스오리진 안전)
//  - applyEndpoint 미설정(<DEPLOY_ID> 그대로)이면 슬랙 신청 안내로 폴백
//  - 하단 플로팅 CTA는 document.body로 portal (scaler transform 밖) → fixed가 viewport에 고정
//  - 시즌 종료 시 app.jsx screens 배열에서 'expedition' 주석 처리

const EXPEDITION = {
  // 배포 후 Apps Script 웹앱 /exec URL로 교체 (선행 준비물 §2)
  applyEndpoint: 'https://script.google.com/macros/s/AKfycbwRygO5DaybmUOnVTGm78vO2MgV24xHnkG6w7y-j4MWOn9jimwCII_kQnwXD0AY07Fo/exec',
  applyChannel: '#gc-피플팀',          // 폴백 안내용 슬랙 채널
  maxDoggikkun: 8,                     // 선착순 정원
  currentMonth: 8,                     // 이번 달 (강조 + 신청 회차)
  axeTime: '9월 25일 (금) 9:00~10:00',  // 이번 회차 도끼타임 (모달에 노출)
  // months: 여러 달에 걸쳐 읽는 책 (분량 많은 경우). label 있으면 카드에 그대로 표시.
  books: [
    { month: 7,  title: '사피엔스',         author: '유발 하라리',      theme: '인간', note: '우리는 어쩌다 지금의 인간이 되었나', cover: 'https://image.aladin.co.kr/product/31424/4/cover500/k482832219_1.jpg' },
    { month: 8,  months: [8, 9], label: '8-9월',
                 title: '총, 균, 쇠',       author: '재레드 다이아몬드', theme: '문명', note: '문명의 운명을 가른 것',          cover: 'https://image.aladin.co.kr/product/31629/43/cover500/8934942460_1.jpg' },
    { month: 10, title: '코스모스',         author: '칼 세이건',        theme: '우주', note: '창백한 푸른 점에서 우주로',        cover: 'https://image.aladin.co.kr/product/54/7/cover500/898371154x_2.jpg' },
    { month: 11, title: '소크라테스의 변명', author: '플라톤',          theme: '개인', note: '검토하지 않는 삶은 살 가치가 없다',  cover: 'https://image.aladin.co.kr/product/21679/27/cover500/k252636705_1.jpg' },
    { month: 12, title: '자유론',           author: '존 스튜어트 밀',   theme: '사회', note: '개인의 자유는 어디까지인가',       cover: 'https://image.aladin.co.kr/product/14712/56/cover500/s732635364_3.jpg' },
    // 한비자(조직) — 2026 하반기 라인업에서 보류. 다음 시즌 후보
  ],
  // 이번 달 도끼꾼 — 슬랙 모집 결과를 적으면 '이번 달' 섹션에 전시. 비우면 자동 숨김.
  doggikkun: [],   // 예: [{ name: '김규리', part: '1부' }, ...]
  // 상품 이미지는 web/assets/ 에 넣고 img 경로 지정 (예: 'assets/reward-2.png')
  rewards: [
    { stamps: 2, label: '독서용 인덱스',       img: 'assets/reward-2.jpg',  contain: false },
    { stamps: 4, label: '독서링',             img: 'assets/reward-4.jpg',  contain: false },
    { stamps: 6, label: '교보문고 상품권 5만원', img: 'assets/reward-6.png', contain: true },
  ],
};

window.expeditionConfig = EXPEDITION;

// === 신청 API (JSONP) — expedition.jsx + admin.jsx 공유 ===
window.expeditionApi = {
  isConfigured() {
    const e = EXPEDITION.applyEndpoint || '';
    return e.indexOf('<') === -1 && e.indexOf('script.google.com') !== -1;
  },
  // 단일 JSONP 호출. params를 쿼리로 붙이고 callback으로 응답 수신
  call(params) {
    return new Promise((resolve, reject) => {
      if (!this.isConfigured()) { reject(new Error('endpoint 미설정')); return; }
      const cb = 'expCb_' + Date.now() + '_' + Math.floor(Math.random() * 1e6);
      let done = false;
      const s = document.createElement('script');
      const cleanup = () => {
        try { delete window[cb]; } catch (_) { window[cb] = undefined; }
        if (s.parentNode) s.parentNode.removeChild(s);
        clearTimeout(timer);
      };
      const timer = setTimeout(() => {
        if (done) return; done = true; cleanup();
        reject(new Error('시간 초과'));
      }, 12000);
      window[cb] = (data) => { if (done) return; done = true; cleanup(); resolve(data); };
      const qs = Object.keys(params || {})
        .map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
        .join('&');
      s.src = EXPEDITION.applyEndpoint + '?callback=' + cb + (qs ? '&' + qs : '');
      s.onerror = () => { if (done) return; done = true; cleanup(); reject(new Error('네트워크 오류')); };
      document.body.appendChild(s);
    });
  },
  list() { return this.call({}); },                      // 신청자 전체
  apply(name, role, month) {                              // 신청 적재
    return this.call({ action: 'apply', name, role: role || '', month: String(month) });
  },
};

const Expedition = ({ isMobile = false }) => {
  const t = window.tokens;
  const cfg = EXPEDITION;
  const api = window.expeditionApi;

  const [name, setName] = React.useState('');
  const [appliedName, setAppliedName] = React.useState(''); // 완료 메시지에 쓸 제출 시점 이름
  const [status, setStatus] = React.useState('idle'); // idle | sending | done | dup | error
  const [count, setCount] = React.useState(null);      // 이번 달 신청 인원
  const configured = api.isConfigured();
  const nameRef = React.useRef(null);

  // 홈·서재와 동일 모델(스케일러가 1440 디자인을 축소). 데스크탑 6열 / 모바일 3열.
  const cols = isMobile ? 3 : cfg.books.length;
  // 폰트: 모바일 m / 그 외 d. (태블릿 tb 인자는 스케일러가 처리하므로 미사용)
  const fs = (m, tb, d) => (isMobile ? m : d);

  const monthCount = (list) =>
    (list || []).filter(a => String(a.month) === String(cfg.currentMonth)).length;

  // 마운트 시 이번 달 신청 인원 1회 조회 (실패해도 조용히)
  React.useEffect(() => {
    if (!configured) return;
    let alive = true;
    api.list().then(res => {
      if (alive && res && res.applicants) setCount(monthCount(res.applicants));
    }).catch(() => {});
    return () => { alive = false; };
  }, []);

  // 하단 플로팅 버튼 → 신청 팝업(모달) 열기
  const [modalOpen, setModalOpen] = React.useState(false);
  React.useEffect(() => {
    if (!modalOpen) return;
    setStatus('idle'); setName('');   // 열 때마다 깔끔하게 초기화
    setTimeout(() => { if (nameRef.current) nameRef.current.focus(); }, 50);
  }, [modalOpen]);

  const submit = (e) => {
    if (e) e.preventDefault();
    const nm = name.trim();
    if (!nm || !configured) { setStatus('error'); if (nameRef.current) nameRef.current.focus(); return; }
    setStatus('sending');
    setAppliedName(nm);
    api.apply(nm, '', cfg.currentMonth).then(res => {
      if (res && res.applicants) setCount(monthCount(res.applicants));
      setStatus(res && res.status === 'duplicate' ? 'dup' : 'done');
    }).catch(() => { setStatus('error'); });
  };

  // ---------- 공통 스타일 헬퍼 ----------
  const PAD = isMobile ? '0 20px' : '0 64px';
  const Kicker = ({ children }) => (
    <div style={{
      fontSize: isMobile ? 13 : 14, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase',
      color: t.color.blue, marginBottom: isMobile ? 12 : 16,
    }}>{children}</div>
  );
  const Rule = () => (
    <div style={{ height: 1, background: t.color.ruleSoft, margin: isMobile ? '44px 20px' : '64px 64px' }} />
  );

  // 여러 달에 걸쳐 읽는 책(months)은 해당 기간 내내 '이번 책'으로 강조
  const isCurrent = (b) => (b.months || [b.month]).some(m => Number(m) === Number(cfg.currentMonth));
  const currentBook = cfg.books.find(isCurrent) || cfg.books[0];

  // ---------- 책 카드 (표지 포함) ----------
  const Cover = ({ b }) => (
    b.cover
      ? <img src={b.cover} alt={b.title} loading="lazy" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
      : <span style={{ color: t.color.mutedLight, fontSize: 13 }}>표지 준비 중</span>
  );
  const CardText = ({ b }) => {
    const cur = isCurrent(b);
    // 긴 제목(소크라테스의 변명 등)은 줄바꿈 안 되게 폰트 한 단계 축소
    const longTitle = (b.title || '').length > 7;
    const titleSize = fs(17, 20, 24) - (longTitle ? fs(2, 2, 4) : 0);
    return (
      <>
        <div style={{ fontSize: fs(14, 15, 17), fontWeight: 700, letterSpacing: '0.02em', color: t.color.mutedLight, fontVariantNumeric: 'tabular-nums', marginBottom: fs(4, 5, 7) }}>{b.label || `${b.month}월`}</div>
        <div style={{ fontSize: titleSize, fontWeight: 800, letterSpacing: '-0.03em', lineHeight: 1.18, color: cur ? t.color.blue : t.color.ink }}>{b.title}</div>
        <div style={{ fontSize: fs(14, 15, 16), color: t.color.muted, fontWeight: 500, marginTop: 2 }}>{b.author}</div>
      </>
    );
  };

  // horizontal: 표지 좌측 + 텍스트 우측 (모바일 그리드 / 이번 달 큰 카드)
  // vertical:   표지 상단 + 텍스트 하단 (데스크탑 6열 그리드)
  const BookCard = ({ b, horizontal }) => {
    const cur = isCurrent(b);
    const frame = {
      position: 'relative', background: cur ? t.color.blueSoft : '#fff',
      border: `1px solid ${cur ? t.color.blue : t.color.ruleSoft}`, overflow: 'hidden',
    };
    if (horizontal) {
      return (
        <div style={{ ...frame, display: 'flex', gap: isMobile ? 14 : 18, padding: isMobile ? 14 : 16 }}>
          <div style={{ flex: `0 0 ${isMobile ? 96 : 132}px`, width: isMobile ? 96 : 132, aspectRatio: '2 / 3', background: t.color.cream, overflow: 'hidden', display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: '0 4px 12px -4px rgba(0,0,0,0.22)' }}>
            <Cover b={b} />
          </div>
          <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', paddingTop: 2 }}>
            <CardText b={b} />
          </div>
        </div>
      );
    }
    return (
      <div style={{ ...frame, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
        <div style={{ width: '100%', aspectRatio: '2 / 3', background: '#fff', overflow: 'hidden', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <Cover b={b} />
        </div>
        <div style={{ padding: isMobile ? '10px 11px 13px' : '16px 16px 18px', display: 'flex', flexDirection: 'column' }}>
          <CardText b={b} />
        </div>
      </div>
    );
  };

  // ---------- 스텝 카드 ----------
  const steps = [
    { n: '①', title: '담당 파트 배정', desc: '책 목차를 도끼꾼 수만큼 균등하게 나눠 한 파트를 맡아요.' },
    { n: '②', title: '핵심·인상 정리', desc: '맡은 파트의 핵심 내용과 인상 깊었던 부분을 정리해요.' },
    { n: '③', title: '도끼타임 발표', desc: '4주차 도끼타임(9:30~10:00)에서 순서대로 내 파트를 소개해요.' },
  ];

  return (
    <div style={{
      width: isMobile ? '100%' : 1440,
      padding: isMobile ? '24px 0 120px' : '48px 0 120px',
      fontFamily: t.font.sans, color: t.color.ink, position: 'relative',
    }}>

      {/* ===== 1. 히어로 — 서재 탭과 동일 형식 (라벨 + 큰 타이틀) ===== */}
      <div style={{ padding: PAD }}>
        <div style={{
          fontFamily: t.font.sans, fontSize: fs(16, 18, 22), fontWeight: 700,
          color: t.color.mutedLight, marginBottom: isMobile ? 8 : 12,
        }}>
          2026 하반기 그란데 독서타임
        </div>
        <div style={{
          fontSize: fs(42, 58, 72), fontWeight: 700, letterSpacing: '-0.04em',
          lineHeight: 1, color: t.color.ink, whiteSpace: 'nowrap',
        }}>
          <span style={{ color: t.color.blue }}>도끼책</span> 원정대
        </div>
        <div style={{
          fontSize: fs(16, 17, 18), fontWeight: 500, letterSpacing: '-0.01em',
          color: t.color.muted, marginTop: isMobile ? 14 : 18, fontStyle: 'italic',
          lineHeight: 1.5, maxWidth: 600,
        }}>
          “책은 우리 안의 꽁꽁 얼어붙은 바다를 깨는 도끼여야 한다.”
          <span style={{ color: t.color.mutedLight, marginLeft: 7 }}>— 프란츠 카프카</span>
        </div>
        <div style={{
          fontSize: fs(16, 19, 22), fontWeight: 500, color: t.color.inkSoft,
          lineHeight: 1.7, letterSpacing: '-0.01em', marginTop: isMobile ? 20 : 26, maxWidth: 680,
        }}>
          생각의 틀을 깨는 ‘도끼 같은 책’을 독서타임에 함께 읽어요.<br />
          목차를 나눠 맡아 읽고, 회차 마지막 금요일에 모여 각자 파트를 소개합니다.
        </div>
      </div>

      {/* ===== 2. 여정 — 책 6권 ===== */}
      <div style={{ padding: PAD, marginTop: isMobile ? 28 : 44 }}>
        {/* 책 6권 — 데스크탑 6열 한 줄 / 모바일·태블릿 3열 2줄 */}
        <div style={{
          display: 'grid',
          gridTemplateColumns: `repeat(${cols}, 1fr)`,
          gap: isMobile ? 8 : 12,
        }}>
          {cfg.books.map(b => <BookCard key={b.month} b={b} />)}
        </div>
      </div>

      {/* ===== 3. 스탬프 적립 + 리워드 ===== */}
      <div style={{ padding: PAD, marginTop: isMobile ? 40 : 60 }}>
        <div style={{ fontSize: fs(17, 19, 22), color: t.color.ink, fontWeight: 700, lineHeight: 1.45, letterSpacing: '-0.02em', maxWidth: 860 }}>
          회차 마지막 주 금요일 <b style={{ color: t.color.blue }}>‘도끼타임’</b> 참여 시 <b style={{ color: t.color.blue }}>스탬프 1장</b>, 도끼꾼으로 발표하면 <b style={{ color: t.color.blue }}>추가 1장 더!</b>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: isMobile ? 8 : 14, marginTop: isMobile ? 20 : 28 }}>
          {cfg.rewards.map(r => (
            <div key={r.stamps} style={{ background: '#fff', overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
              <div style={{ position: 'relative', height: isMobile ? 150 : 230, background: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden' }}>
                <div style={{
                  position: 'absolute', top: 0, left: 0, zIndex: 2,
                  background: t.color.blue, color: '#fff',
                  fontSize: fs(15, 17, 20), fontWeight: 800, letterSpacing: '-0.02em',
                  padding: isMobile ? '5px 11px' : '7px 15px',
                }}>{r.stamps}장</div>
                {r.img
                  ? <img src={r.img} alt={r.label} loading="lazy" style={r.contain
                      ? { maxWidth: '100%', maxHeight: '100%', objectFit: 'contain' }
                      : { width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
                  : <span style={{ fontSize: fs(11, 12, 13), color: t.color.mutedLight }}>상품 이미지</span>}
              </div>
              <div style={{ padding: isMobile ? '11px 11px 13px' : '14px 16px 16px' }}>
                <div style={{ fontSize: fs(14, 15, 17), color: t.color.ink, fontWeight: 700, letterSpacing: '-0.01em', lineHeight: 1.35 }}>{r.label}</div>
              </div>
            </div>
          ))}
        </div>
      </div>

      {/* ===== 하단 플로팅 CTA — body로 portal해서 viewport에 고정 (scaler transform 무시) ===== */}
      {/* 회차 모집 중일 때만 노출. 선정 완료되면 true → false 로 숨김 (2026-08: 8월 «총, 균, 쇠» 모집 중) */}
      {true && ReactDOM.createPortal(
        <div
          onClick={() => setModalOpen(true)}
          role="button"
          style={{
            position: 'fixed', left: '50%', bottom: 26, transform: 'translateX(-50%)',
            zIndex: 9999, cursor: 'pointer',
            display: 'flex', alignItems: 'center', gap: 10,
            background: window.tokens.color.ink, color: '#fff',
            padding: '15px 30px', borderRadius: 999,
            fontFamily: window.tokens.font.sans, fontSize: 17, fontWeight: 700, letterSpacing: '-0.01em',
            whiteSpace: 'nowrap', boxShadow: '0 14px 36px -8px rgba(0,0,0,0.45)',
            border: '1px solid rgba(255,255,255,0.08)',
          }}
          onMouseEnter={(e) => { e.currentTarget.style.background = window.tokens.color.blue; }}
          onMouseLeave={(e) => { e.currentTarget.style.background = window.tokens.color.ink; }}
        >
          🪓 도끼꾼 신청하기
          <span style={{ fontSize: 18, lineHeight: 1 }}>→</span>
        </div>,
        document.body
      )}

      {/* ===== 신청 팝업 (모달) — body로 portal ===== */}
      {modalOpen && ReactDOM.createPortal(
        <div
          onClick={() => setModalOpen(false)}
          style={{
            position: 'fixed', inset: 0, zIndex: 10000,
            background: 'rgba(10,10,10,0.55)',
            display: 'flex', alignItems: isMobile ? 'flex-end' : 'center', justifyContent: 'center',
            padding: isMobile ? 0 : 20,
          }}
        >
          <div
            onClick={(e) => e.stopPropagation()}
            style={{
              background: '#fff', width: isMobile ? '100%' : 460, maxWidth: '100%',
              borderRadius: isMobile ? '18px 18px 0 0' : 14,
              padding: isMobile ? '28px 22px 32px' : '34px 34px 30px',
              fontFamily: t.font.sans, position: 'relative',
              boxShadow: '0 24px 60px -12px rgba(0,0,0,0.5)',
            }}
          >
            <div onClick={() => setModalOpen(false)} style={{
              position: 'absolute', top: 14, right: 18, fontSize: 24, lineHeight: 1,
              color: t.color.mutedLight, cursor: 'pointer',
            }}>×</div>

            <div style={{ fontSize: 15, color: t.color.muted, fontWeight: 600, letterSpacing: '-0.01em' }}>
              {currentBook.label || `${cfg.currentMonth}월`}의 ‘도끼 같은 책’
            </div>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, marginTop: 4, flexWrap: 'wrap' }}>
              <span style={{ fontSize: 30, fontWeight: 800, letterSpacing: '-0.03em', color: t.color.blue }}>«{currentBook.title}»</span>
              <span style={{ fontSize: 15, color: t.color.muted, fontWeight: 500 }}>{currentBook.author}</span>
            </div>
            {cfg.axeTime && (
              <div style={{ fontSize: 15, color: t.color.muted, fontWeight: 500, marginTop: 10, letterSpacing: '-0.01em' }}>
                도끼타임 <b style={{ color: t.color.inkSoft, fontWeight: 700 }}>{cfg.axeTime}</b>
              </div>
            )}

            <form onSubmit={submit} style={{ display: 'flex', flexDirection: 'row', gap: 10, marginTop: 24 }}>
              <input
                ref={nameRef}
                value={name}
                onChange={(e) => { setName(e.target.value); if (status !== 'idle') setStatus('idle'); }}
                placeholder="이름을 입력하세요"
                style={{
                  flex: 1, minWidth: 0, padding: '15px 18px',
                  border: `1px solid ${status === 'error' ? '#C53030' : t.color.ruleSoft}`,
                  fontSize: 17, fontFamily: t.font.sans, outline: 'none', color: t.color.ink,
                  letterSpacing: '-0.01em', background: '#fff', boxSizing: 'border-box',
                }}
              />
              {(() => {
                const okState = status === 'done' || status === 'dup';
                return (
                  <button type="submit" disabled={status === 'sending' || okState} style={{
                    padding: '15px 28px', whiteSpace: 'nowrap', flexShrink: 0,
                    background: okState ? t.color.blue : status === 'sending' ? '#E2E2E2' : t.color.ink,
                    color: status === 'sending' ? t.color.muted : '#fff',
                    fontSize: 17, fontWeight: 700, border: 'none',
                    cursor: status === 'sending' ? 'wait' : okState ? 'default' : 'pointer',
                    fontFamily: t.font.sans, letterSpacing: '-0.01em', transition: 'background 0.2s',
                  }}>
                    {status === 'sending' ? '신청 중…' : okState ? '완료' : '신청'}
                  </button>
                );
              })()}
            </form>

            {(status === 'done' || status === 'dup') && (
              <div style={{
                marginTop: 18, fontSize: 15, lineHeight: 1.65, letterSpacing: '-0.01em',
                color: t.color.inkSoft, fontWeight: 500,
              }}>
                신청해주셔서 감사합니다.<br />차주 내에 개인 슬랙을 통해 자세히 안내드릴게요!<br />
                <b style={{ color: t.color.blue }}>{appliedName}</b>님의 독서를 응원합니다 ❤️
              </div>
            )}
          </div>
        </div>,
        document.body
      )}

    </div>
  );
};

window.Expedition = Expedition;
