// KASHA website — booking flow (4 steps): 촬영 선택 → 옵션 → 일정(캘린더) → 정보
// · 촬영 상품/옵션은 KASHADB(관리자)에서 파생 (옵션 = 상품 고유 + 전역 템플릿)
// · 예약 시간대 09:00~21:00 1시간 간격, 상품의 최소 촬영시간(minutes)만큼 연속 슬롯이 비어야 예약 가능
const OPEN_HOUR = 9, CLOSE_HOUR = 22; // 마지막 촬영 종료는 22:00
const DOW_KR = ["일", "월", "화", "수", "목", "금", "토"];
const pad2b = (n) => (n < 10 ? "0" : "") + n;
const SLOT_TIMES = Array.from({ length: 21 - OPEN_HOUR + 1 }, (_, i) => pad2b(OPEN_HOUR + i) + ":00"); // 09:00..21:00
const dateKeyOf = (s) => { const m = String(s || "").match(/(\d{4})\.(\d{2})\.(\d{2})/); return m ? `${m[1]}.${m[2]}.${m[3]}` : ""; };
const hourOf = (t) => parseInt(String(t).split(":")[0], 10);
const reqSlots = (pkg) => Math.max(1, Math.ceil((((pkg && pkg.minutes) || 60)) / 60));

// 날짜의 시간대 점유 맵 (예약 상품 minutes 기반 연속 점유). hour → "closed" | "pending"
function occupancyMap(allRes, pkgByName, dateKey) {
  const map = {};
  allRes.forEach((r) => {
    if (dateKeyOf(r.date) !== dateKey || r.status === "취소") return;
    const start = hourOf(r.time);
    const span = pkgByName[r.pkg] ? reqSlots(pkgByName[r.pkg]) : 1;
    const level = r.status === "대기" ? "pending" : "closed";
    for (let h = start; h < start + span; h++) { if (map[h] !== "closed") map[h] = level; }
  });
  return map;
}

function BookingScreen({ order, onNavigate }) {
  const { Button, Card, Input, Select, Badge, Icon } = window.DS;
  const packages = window.PACKAGES;
  const pkgByName = {}; window.KASHADB.getPackages().forEach((p) => { pkgByName[p.name] = p; });
  const user = window.KASHADB.getCurrentUser();
  const places = window.PLACES || ["성수 스튜디오"];
  const presetId = (order && order.pkgId) || (packages[0] && packages[0].id);

  const [step, setStep] = React.useState(1);
  const [pkgId, setPkgId] = React.useState(presetId);
  const [selAddons, setSelAddons] = React.useState((order && order.addonIds) || []);
  const [dateKey, setDateKey] = React.useState("");
  const [dateDow, setDateDow] = React.useState("");
  const [time, setTime] = React.useState("");
  const [name, setName] = React.useState((order && order.name) || (user && user.name) || "");
  const [phone, setPhone] = React.useState((order && order.phone) || (user && user.phone) || "");
  const [email, setEmail] = React.useState((order && order.email) || (user && user.email) || "");
  const [place, setPlace] = React.useState(places[0]);

  const pkg = packages.find((p) => p.id === pkgId) || packages[0];
  const addons = window.effectiveAddons(pkg);
  const allRes = window.KASHADB.getReservations();
  const won = (n) => Number(n || 0).toLocaleString("ko-KR");
  const req = reqSlots(pkg);

  const addonTotal = addons.filter((a) => selAddons.includes(a.id)).reduce((s, a) => s + a.price, 0);
  const total = (pkg ? pkg.priceNum : 0) + addonTotal;
  const toggleAddon = (id) => setSelAddons((s) => (s.includes(id) ? s.filter((x) => x !== id) : s.concat([id])));

  // 선택 날짜의 슬롯 점유 + 시작 가능 여부(연속 req시간 비어있고 22시 내 종료)
  const occ = dateKey ? occupancyMap(allRes, pkgByName, dateKey) : {};
  const startSelectable = (h) => {
    if (h + req > CLOSE_HOUR) return false;
    for (let i = h; i < h + req; i++) { if (occ[i]) return false; }
    return true;
  };

  const canNext = step === 1 ? !!pkg
    : step === 2 ? true
    : step === 3 ? (!!dateKey && !!time)
    : (!!name && !!phone && /.+@.+\..+/.test(email));

  const next = () => {
    if (step < 4) return setStep(step + 1);
    const dateStr = dateKey ? `${dateKey} (${dateDow})` : "";
    onNavigate("payment", { pkgId, date: dateStr, time, name, phone, email, place, addonIds: selAddons });
  };
  const back = () => (step > 1 ? setStep(step - 1) : onNavigate("home"));
  const titles = ["어떤 촬영을 원하세요?", "옵션을 추가해 보세요", "날짜와 시간을 선택하세요", "예약자 정보를 입력하세요"];

  return (
    <div style={{ maxWidth: 760, margin: "0 auto", padding: "48px 24px 96px" }}>
      <button onClick={back} style={{ border: "none", background: "transparent", display: "flex", alignItems: "center", gap: 6, color: "var(--text-secondary)", fontSize: 15, fontWeight: 600, cursor: "pointer", padding: 0, marginBottom: 22 }}>
        <Icon name="arrowLeft" size={18} /> 뒤로
      </button>

      <Stepper step={step} />
      <h1 style={{ fontSize: "var(--text-title-1)", letterSpacing: "var(--tracking-title)", marginTop: 28 }}>{titles[step - 1]}</h1>

      <div key={step} style={{ marginTop: 28, animation: "kashaStep var(--dur-base) var(--ease-ios)" }}>
        <style>{`@keyframes kashaStep{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}`}</style>

        {/* STEP 1 — 촬영 선택 */}
        {step === 1 && (
          <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
            {packages.map((p) => {
              const active = pkgId === p.id;
              return (
                <Card key={p.id} interactive onClick={() => setPkgId(p.id)}
                  style={{ border: `1.5px solid ${active ? "var(--ink)" : "var(--border-subtle)"}`, boxShadow: active ? "var(--shadow-md)" : "var(--shadow-card)" }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
                    <span style={{ width: 22, height: 22, borderRadius: "50%", border: `2px solid ${active ? "var(--ink)" : "var(--border-strong)"}`, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
                      {active && <span style={{ width: 12, height: 12, borderRadius: "50%", background: "var(--ink)" }} />}
                    </span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                        <span style={{ fontSize: 18, fontWeight: 700, color: "var(--text-strong)", whiteSpace: "nowrap" }}>{p.name}</span>
                        {p.popular && <Badge tone="accent">인기</Badge>}
                      </div>
                      <div style={{ fontSize: 13, color: "var(--text-tertiary)", marginTop: 4 }}>{p.time} · {p.cuts}</div>
                    </div>
                    <div style={{ fontSize: 18, fontWeight: 700, color: "var(--text-strong)" }}>{p.price}<span style={{ fontSize: 13, color: "var(--text-tertiary)", fontWeight: 500 }}>원</span></div>
                  </div>
                </Card>
              );
            })}
          </div>
        )}

        {/* STEP 2 — 옵션 (상품 고유 + 전역 템플릿) */}
        {step === 2 && (
          <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
            {addons.length === 0 ? (
              <Card elevation="none" style={{ background: "var(--gray-50)", border: "none", textAlign: "center", padding: "40px 24px" }}>
                <Icon name="sparkles" size={28} color="var(--gray-400)" />
                <p style={{ marginTop: 12, color: "var(--text-secondary)", fontSize: 15 }}>추가 옵션이 없어요. 바로 다음 단계로 진행해 주세요.</p>
              </Card>
            ) : addons.map((a) => {
              const on = selAddons.includes(a.id);
              return (
                <button key={a.id} onClick={() => toggleAddon(a.id)}
                  style={{ display: "flex", alignItems: "center", gap: 12, padding: "18px 20px", borderRadius: "var(--radius-md)", border: `1.5px solid ${on ? "var(--ink)" : "var(--border-subtle)"}`, background: on ? "var(--gray-50)" : "#fff", cursor: "pointer", fontFamily: "var(--font-sans)", textAlign: "left", transition: "border-color var(--dur-fast) var(--ease-standard)" }}>
                  <span style={{ width: 24, height: 24, borderRadius: 8, background: on ? "var(--ink)" : "#fff", border: `1.5px solid ${on ? "var(--ink)" : "var(--border-strong)"}`, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
                    {on && <Icon name="check" size={16} color="#fff" strokeWidth={3} />}
                  </span>
                  <span style={{ flex: 1, fontSize: 16, fontWeight: 600, color: "var(--text-strong)" }}>{a.label}
                    {a.source === "template" && <span style={{ fontSize: 11, fontWeight: 700, color: "var(--blue-500)", marginLeft: 8, background: "var(--blue-50)", padding: "2px 7px", borderRadius: 999 }}>공통</span>}
                  </span>
                  <span style={{ fontSize: 16, fontWeight: 700, color: "var(--text-strong)" }}>+{won(a.price)}원</span>
                </button>
              );
            })}
            {addons.length > 0 && (
              <div style={{ display: "flex", justifyContent: "space-between", padding: "16px 4px 0", fontSize: 15 }}>
                <span style={{ color: "var(--text-secondary)" }}>선택한 옵션</span>
                <strong style={{ color: "var(--text-strong)" }}>+{won(addonTotal)}원</strong>
              </div>
            )}
          </div>
        )}

        {/* STEP 3 — 일정 (캘린더 + 슬롯) */}
        {step === 3 && (
          <div style={{ display: "flex", flexDirection: "column", gap: 24 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "12px 16px", borderRadius: "var(--radius-md)", background: "var(--blue-50)", color: "var(--blue-700)", fontSize: 13.5 }}>
              <Icon name="clock" size={17} color="var(--blue-500)" />
              {pkg.name}은(는) 최소 <strong>&nbsp;{pkg.time}&nbsp;</strong>(약 {req}시간) 촬영이에요. 연속으로 비어있는 시간만 선택할 수 있어요.
            </div>
            <BookingCalendar selectedKey={dateKey} onPick={(k, dow) => { setDateKey(k); setDateDow(dow); setTime(""); }} allRes={allRes} pkgByName={pkgByName} />
            {dateKey && (
              <div>
                <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 12 }}>
                  <span style={{ fontSize: 14, fontWeight: 700, color: "var(--text-strong)" }}>{dateKey} ({dateDow}) 예약 현황</span>
                  <Legend />
                </div>
                <div style={{ display: "grid", gridTemplateColumns: "repeat(2,1fr)", gap: 8 }}>
                  {SLOT_TIMES.map((t) => {
                    const h = hourOf(t);
                    const st = occ[h] || "available";
                    const sel = time === t;
                    const selectable = st === "available" && startSelectable(h);
                    const meta = st === "closed" ? { label: "마감", color: "var(--red-500)", bg: "var(--red-50)" }
                      : st === "pending" ? { label: "대기 중", color: "var(--yellow-600)", bg: "var(--yellow-50)" }
                      : selectable ? { label: "예약 가능", color: "var(--green-600)", bg: "var(--green-50)" }
                      : { label: "시간 부족", color: "var(--text-tertiary)", bg: "var(--gray-100)" };
                    return (
                      <button key={t} disabled={!selectable} onClick={() => selectable && setTime(t)}
                        style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "14px 16px", borderRadius: "var(--radius-md)", border: `1.5px solid ${sel ? "var(--ink)" : "var(--border-subtle)"}`, background: sel ? "var(--ink)" : selectable ? "#fff" : "var(--gray-50)", cursor: selectable ? "pointer" : "not-allowed", fontFamily: "var(--font-sans)", opacity: selectable ? 1 : 0.65, transition: "border-color var(--dur-fast) var(--ease-standard)" }}>
                        <span style={{ display: "flex", alignItems: "center", gap: 8 }}>
                          <Icon name="clock" size={16} color={sel ? "#fff" : "var(--gray-500)"} />
                          <span style={{ fontSize: 15, fontWeight: 700, color: sel ? "#fff" : "var(--text-strong)" }}>{t}</span>
                        </span>
                        <span style={{ fontSize: 12, fontWeight: 700, color: sel ? "#fff" : meta.color, background: sel ? "rgba(255,255,255,0.18)" : meta.bg, padding: "4px 9px", borderRadius: 999 }}>{sel ? "선택됨" : meta.label}</span>
                      </button>
                    );
                  })}
                </div>
              </div>
            )}
          </div>
        )}

        {/* STEP 4 — 정보 */}
        {step === 4 && (
          <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
            <Input label="예약자 이름" value={name} onChange={(e) => setName(e.target.value)} placeholder="홍길동" />
            <Input label="연락처" value={phone} onChange={(e) => setPhone(e.target.value)} placeholder="010-0000-0000" />
            <Input label="이메일" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="you@example.com" />
            <p style={{ fontSize: 12.5, color: "var(--text-tertiary)", marginTop: -8 }}>예약 확정·결제 영수증을 이 이메일로 보내드려요.</p>
            <Select label="촬영 장소" value={place} onChange={(e) => setPlace(e.target.value)} options={places} placeholder="" />
            <Card elevation="none" style={{ background: "var(--gray-50)", border: "none" }}>
              <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
                <SumRow label="촬영" value={pkg ? `${pkg.name} · ${pkg.time}` : ""} />
                <SumRow label="일정" value={dateKey ? `${dateKey} (${dateDow}) · ${time}` : "미정"} />
                {selAddons.length > 0 && <SumRow label="옵션" value={`${selAddons.length}개 · +${won(addonTotal)}원`} />}
                <div style={{ borderTop: "1px solid var(--border-subtle)", paddingTop: 10, display: "flex", justifyContent: "space-between" }}>
                  <strong style={{ color: "var(--text-strong)", fontSize: 15 }}>예상 결제금액</strong>
                  <strong style={{ color: "var(--text-strong)", fontSize: 17 }}>{won(total)}원</strong>
                </div>
              </div>
            </Card>
          </div>
        )}
      </div>

      <div style={{ marginTop: 32 }}>
        <Button variant="primary" size="lg" fullWidth disabled={!canNext} onClick={next}>{step < 4 ? "다음" : "결제하기"}</Button>
      </div>
    </div>
  );
}

// ── 예약 캘린더 ──────────────────────────────────────────────────────
function BookingCalendar({ selectedKey, onPick, allRes, pkgByName }) {
  const { Icon, Card } = window.DS;
  const today = new Date(); today.setHours(0, 0, 0, 0);
  const [y, setY] = React.useState(2026);
  const [mo, setMo] = React.useState(6); // 7월

  const first = new Date(y, mo, 1);
  const startDow = first.getDay();
  const daysInMonth = new Date(y, mo + 1, 0).getDate();
  const cells = [];
  for (let i = 0; i < startDow; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(d);

  const keyOf = (d) => `${y}.${pad2b(mo + 1)}.${pad2b(d)}`;
  const occOf = (k) => occupancyMap(allRes, pkgByName, k);
  const dayFull = (k) => { const o = occOf(k); return SLOT_TIMES.every((t) => o[hourOf(t)]); };
  const dayHasRes = (k) => { const o = occOf(k); return SLOT_TIMES.some((t) => o[hourOf(t)]); };

  const move = (delta) => { let nm = mo + delta, ny = y; if (nm < 0) { nm = 11; ny--; } if (nm > 11) { nm = 0; ny++; } setMo(nm); setY(ny); };

  return (
    <Card>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 16 }}>
        <button onClick={() => move(-1)} aria-label="이전 달" style={{ width: 36, height: 36, borderRadius: 10, border: "1px solid var(--border-subtle)", background: "#fff", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center" }}><Icon name="chevronLeft" size={18} /></button>
        <strong style={{ fontSize: 17, color: "var(--text-strong)", letterSpacing: "var(--tracking-title)" }}>{y}년 {mo + 1}월</strong>
        <button onClick={() => move(1)} aria-label="다음 달" style={{ width: 36, height: 36, borderRadius: 10, border: "1px solid var(--border-subtle)", background: "#fff", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center" }}><Icon name="chevronRight" size={18} /></button>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(7,1fr)", gap: 4, textAlign: "center" }}>
        {DOW_KR.map((d, i) => (
          <div key={d} style={{ fontSize: 12, fontWeight: 700, color: i === 0 ? "var(--red-500)" : i === 6 ? "var(--blue-500)" : "var(--text-tertiary)", padding: "4px 0 8px" }}>{d}</div>
        ))}
        {cells.map((d, i) => {
          if (d === null) return <div key={"e" + i} />;
          const k = keyOf(d);
          const dateObj = new Date(y, mo, d);
          const past = dateObj < today;
          const full = dayFull(k);
          const hasRes = dayHasRes(k);
          const sel = selectedKey === k;
          const disabled = past || full;
          return (
            <button key={k} disabled={disabled} onClick={() => onPick(k, DOW_KR[dateObj.getDay()])}
              style={{ position: "relative", aspectRatio: "1", borderRadius: 12, border: `1.5px solid ${sel ? "var(--ink)" : "transparent"}`, background: sel ? "var(--ink)" : disabled ? "transparent" : "var(--gray-50)", color: sel ? "#fff" : disabled ? "var(--text-disabled)" : "var(--text-strong)", cursor: disabled ? "not-allowed" : "pointer", fontFamily: "var(--font-sans)", fontSize: 15, fontWeight: 700, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 2, transition: "background var(--dur-fast) var(--ease-standard)" }}>
              {d}
              {full ? <span style={{ fontSize: 9, fontWeight: 700, color: sel ? "rgba(255,255,255,0.8)" : "var(--red-500)" }}>마감</span>
                : hasRes && !sel ? <span style={{ width: 5, height: 5, borderRadius: "50%", background: "var(--blue-500)" }} />
                : <span style={{ height: 5 }} />}
            </button>
          );
        })}
      </div>
    </Card>
  );
}

function Legend() {
  const dot = (c) => ({ width: 8, height: 8, borderRadius: "50%", background: c, display: "inline-block" });
  return (
    <div style={{ display: "flex", gap: 12, fontSize: 11, color: "var(--text-tertiary)", marginLeft: "auto" }}>
      <span style={{ display: "flex", alignItems: "center", gap: 4 }}><i style={dot("var(--green-500)")} />가능</span>
      <span style={{ display: "flex", alignItems: "center", gap: 4 }}><i style={dot("var(--yellow-500)")} />대기</span>
      <span style={{ display: "flex", alignItems: "center", gap: 4 }}><i style={dot("var(--red-500)")} />마감</span>
    </div>
  );
}
function SumRow({ label, value }) {
  return (
    <div style={{ display: "flex", justifyContent: "space-between", fontSize: 14 }}>
      <span style={{ color: "var(--text-secondary)" }}>{label}</span>
      <span style={{ color: "var(--text-strong)", fontWeight: 600 }}>{value}</span>
    </div>
  );
}
function Stepper({ step }) {
  const labels = ["촬영 선택", "옵션", "일정", "정보 입력"];
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
      {labels.map((l, i) => {
        const n = i + 1; const active = n <= step;
        return (
          <React.Fragment key={l}>
            <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
              <span style={{ width: 26, height: 26, borderRadius: "50%", background: active ? "var(--ink)" : "var(--gray-200)", color: active ? "#fff" : "var(--text-tertiary)", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 13, fontWeight: 700, transition: "background var(--dur-base) var(--ease-ios)", flexShrink: 0 }}>{n}</span>
              <span style={{ fontSize: 13, fontWeight: 600, color: active ? "var(--text-strong)" : "var(--text-tertiary)", whiteSpace: "nowrap" }}>{l}</span>
            </div>
            {n < 4 && <div style={{ flex: 1, height: 2, background: n < step ? "var(--ink)" : "var(--gray-200)", borderRadius: 2, transition: "background var(--dur-base) var(--ease-ios)" }} />}
          </React.Fragment>
        );
      })}
    </div>
  );
}
window.BookingScreen = BookingScreen;
