// === Bulk price edit ===
function BulkEditScreen({ products, setProducts, productsSource }) {
  const { CATEGORIES } = window.MOCK;
  const isLive = productsSource === "live";
  const [keyword, setKeyword] = useState("");
  const [selectedCats, setSelectedCats] = useState(new Set());
  const [mode, setMode] = useState("percent"); // percent / fixed / set
  const [direction, setDirection] = useState("up");
  const [value, setValue] = useState(10);
  const [previewOpen, setPreviewOpen] = useState(false);
  const [naverSaving, setNaverSaving] = useState(false);
  const [saveProgress, setSaveProgress] = useState(null);
  const abortRef = useRef(false);

  // 라이브 모드면 카테고리 chip을 실제 상품 데이터에서 동적 생성
  const effectiveCategories = useMemo(() => {
    if (!isLive) return CATEGORIES;
    const seen = new Map();
    products.forEach(p => {
      if (p.category && !seen.has(p.category)) {
        seen.set(p.category, { id: p.category, name: p.category, icon: "" });
      }
    });
    return Array.from(seen.values()).sort((a, b) => a.name.localeCompare(b.name, "ko"));
  }, [products, isLive]);

  const matched = useMemo(() => {
    return products.filter(p => {
      if (keyword && !p.name.toLowerCase().includes(keyword.toLowerCase())) return false;
      if (selectedCats.size > 0 && !selectedCats.has(p.category)) return false;
      return true;
    });
  }, [products, keyword, selectedCats]);

  // 가격 계산 — 네이버는 10원 단위만 받음
  const calcNewPrice = (oldPrice) => {
    let np;
    if (mode === "set") np = value;
    else {
      const sign = direction === "up" ? 1 : -1;
      if (mode === "percent") np = oldPrice * (1 + sign * value / 100);
      else np = oldPrice + sign * value;
    }
    np = Math.max(0, Math.round(np / 10) * 10);  // 10원 단위 내림 반올림
    return np;
  };

  // 즉시할인은 절대값이라 판매가 변경해도 그대로 유지 → 할인가 재계산
  const previewRows = matched.map(p => {
    const newPrice = calcNewPrice(p.price);
    const oldDp = p.discountedPrice || p.price;
    const discount = p.price - oldDp;
    const newDiscountedPrice = Math.max(0, newPrice - discount);
    return { ...p, newPrice, oldDiscountedPrice: oldDp, newDiscountedPrice, discount };
  }).filter(p => p.newPrice !== p.price);
  const totalDelta = previewRows.reduce((s, p) => s + (p.newPrice - p.price), 0);

  const toggleCat = (id) => {
    const s = new Set(selectedCats);
    if (s.has(id)) s.delete(id); else s.add(id);
    setSelectedCats(s);
  };

  const apply = async () => {
    if (!isLive) {
      // mock 모드: 즉시 로컬 반영
      setProducts(prev => prev.map(p => {
        const m = previewRows.find(r => r.id === p.id);
        if (!m) return p;
        return { ...p, price: m.newPrice };
      }));
      toast(`${previewRows.length}개 상품의 판매가가 수정되었습니다`);
      setPreviewOpen(false);
      return;
    }
    // 라이브 모드: 순차 PUT
    abortRef.current = false;
    setNaverSaving(true);
    const succeeded = [];
    const failed = [];
    setSaveProgress({ done: 0, total: previewRows.length, succeeded: [], failed: [] });
    for (let i = 0; i < previewRows.length; i++) {
      if (abortRef.current) break;
      const item = previewRows[i];
      try {
        if (!item.originProductNo) throw new Error("originProductNo 누락");
        await window.API.naverChangePrice(item.originProductNo, item.newPrice);
        succeeded.push(item);
      } catch (err) {
        console.error("[bulk-saveToNaver]", item.id, err);
        failed.push({ ...item, error: err.message });
      }
      setSaveProgress({ done: i + 1, total: previewRows.length, succeeded: [...succeeded], failed: [...failed], aborted: abortRef.current });
    }
    // 성공한 것만 products에 반영 (할인가도 재계산)
    if (succeeded.length > 0) {
      const okIds = new Set(succeeded.map(x => x.id));
      setProducts(prev => prev.map(p => {
        if (!okIds.has(p.id)) return p;
        const item = succeeded.find(x => x.id === p.id);
        return { ...p, price: item.newPrice, discountedPrice: item.newDiscountedPrice };
      }));
    }
    setNaverSaving(false);
    if (failed.length === 0 && !abortRef.current) {
      toast(`${succeeded.length}개 가격이 네이버에 반영되었습니다`);
    } else if (abortRef.current) {
      toast(`중지됨 — ${succeeded.length}개 적용, ${previewRows.length - succeeded.length - failed.length}개 미적용`);
    } else {
      toast(`${succeeded.length}개 성공, ${failed.length}개 실패`);
    }
  };

  const abortBulk = () => { abortRef.current = true; };
  const closePreview = () => {
    if (naverSaving) return;
    setPreviewOpen(false);
    setSaveProgress(null);
  };

  return (
    <div className="page">
      <div className="page-header">
        <h1 className="page-title">일괄 가격 수정</h1>
        <p className="page-desc">
          {isLive
            ? `네이버 라이브 ${products.length}개 상품에서 필터 → 미리보기 → 일괄 적용 (10원 단위 반올림)`
            : "키워드와 카테고리로 상품을 필터링한 뒤 일괄로 가격을 변경합니다"}
        </p>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "380px 1fr", gap: 12, alignItems: "flex-start" }} className="dash-grid">
        {/* Left: rule builder */}
        <div className="flex-col gap-3">
          <div className="card">
            <div className="card-header">
              <div className="card-title">1. 대상 상품 필터</div>
            </div>
            <div className="card-body" style={{ display: "flex", flexDirection: "column", gap: 14 }}>
              <Field label="상품명 키워드 포함">
                <div className="input-with-icon">
                  <window.I.Search size={14} className="input-icon" />
                  <input className="input" placeholder="예: 티셔츠, 청소기..." value={keyword} onChange={e => setKeyword(e.target.value)} />
                </div>
              </Field>
              <Field label={`카테고리 (다중 선택)${isLive ? " · 라이브 데이터에서 추출" : ""}`}>
                <div className="row gap-2" style={{ flexWrap: "wrap" }}>
                  {effectiveCategories.map(c => (
                    <button key={c.id} className={"chip " + (selectedCats.has(c.id) ? "active" : "")} onClick={() => toggleCat(c.id)}>
                      {c.icon} {c.name}
                    </button>
                  ))}
                </div>
                <div className="text-xs muted" style={{ marginTop: 6 }}>선택 안 함 = 전체 카테고리</div>
              </Field>
            </div>
          </div>

          <div className="card">
            <div className="card-header">
              <div className="card-title">2. 변경 방식</div>
            </div>
            <div className="card-body" style={{ display: "flex", flexDirection: "column", gap: 14 }}>
              <Field label="수정 방식">
                <div className="seg" style={{ width: "100%" }}>
                  <button className={"seg-btn " + (mode === "percent" ? "active" : "")} onClick={() => setMode("percent")} style={{ flex: 1 }}>정률 (%)</button>
                  <button className={"seg-btn " + (mode === "fixed" ? "active" : "")} onClick={() => setMode("fixed")} style={{ flex: 1 }}>정액 (₩)</button>
                  <button className={"seg-btn " + (mode === "set" ? "active" : "")} onClick={() => setMode("set")} style={{ flex: 1 }}>고정가</button>
                </div>
              </Field>

              {mode !== "set" && (
                <Field label="방향">
                  <div className="seg" style={{ width: "100%" }}>
                    <button className={"seg-btn " + (direction === "up" ? "active" : "")} onClick={() => setDirection("up")} style={{ flex: 1 }}>
                      <window.I.ArrowUp size={12} /> 인상
                    </button>
                    <button className={"seg-btn " + (direction === "down" ? "active" : "")} onClick={() => setDirection("down")} style={{ flex: 1 }}>
                      <window.I.ArrowDown size={12} /> 인하
                    </button>
                  </div>
                </Field>
              )}

              <Field label={mode === "percent" ? "비율 (%)" : "금액 (₩)"}>
                <div className="row gap-2">
                  <input className="input tabular" type="number" value={value} onChange={e => setValue(parseInt(e.target.value) || 0)} />
                  {mode === "percent" && (
                    <div className="row gap-2">
                      {[5, 10, 15].map(v => (
                        <button key={v} className="btn btn-sm" onClick={() => setValue(v)}>{v}%</button>
                      ))}
                    </div>
                  )}
                </div>
              </Field>

              <div style={{ background: "var(--bg-elev)", padding: "10px 12px", borderRadius: 6, fontSize: 12 }}>
                <strong>요약:</strong> {mode === "set" ? `모든 상품을 ${formatKRW(value)}로 통일` :
                  mode === "percent" ? `현재가의 ${value}% ${direction === "up" ? "인상" : "인하"} (10원 단위 반올림)` :
                  `${formatKRW(value)} ${direction === "up" ? "인상" : "인하"}`}
              </div>
            </div>
          </div>

          <button className="btn btn-primary btn-lg" disabled={matched.length === 0} onClick={() => setPreviewOpen(true)}>
            <window.I.Eye size={14} /> {matched.length}개 상품 미리보기 후 적용
          </button>
        </div>

        {/* Right: matched preview */}
        <div className="card">
          <div className="card-header">
            <div className="card-title">매칭된 상품 ({matched.length})</div>
            <div className="right text-sm muted">총 변동액: <strong className="tabular" style={{ color: totalDelta >= 0 ? "var(--accent)" : "var(--danger)" }}>
              {totalDelta >= 0 ? "+" : ""}{formatKRW(totalDelta)}
            </strong></div>
          </div>
          <div style={{ maxHeight: 600, overflow: "auto" }}>
            {previewRows.length === 0 ? (
              <div className="empty">
                <window.I.Filter size={32} className="empty-icon" />
                <div>필터 조건에 맞는 상품이 없습니다</div>
              </div>
            ) : (
              <table className="table">
                <thead>
                  <tr>
                    <th>상품</th>
                    <th className="numeric">현재가</th>
                    <th className="numeric">변경가</th>
                    <th className="numeric">차액</th>
                  </tr>
                </thead>
                <tbody>
                  {previewRows.map(p => {
                    const diff = p.newPrice - p.price;
                    const hasDiscount = p.discount > 0;
                    return (
                      <tr key={p.id}>
                        <td>
                          <div className="product-cell">
                            <ProductThumb tone={p.tone} name={p.name} size={32} />
                            <div style={{ minWidth: 0 }}>
                              <div className="product-name" style={{ fontSize: 13 }}>{p.name}</div>
                              {hasDiscount && (
                                <div className="text-xs" style={{ color: "var(--accent)", marginTop: 1 }}>
                                  할인가 {formatKRW(p.oldDiscountedPrice)} → {formatKRW(p.newDiscountedPrice)}
                                </div>
                              )}
                            </div>
                          </div>
                        </td>
                        <td className="numeric muted">{formatKRW(p.price)}</td>
                        <td className="numeric" style={{ fontWeight: 600 }}>{formatKRW(p.newPrice)}</td>
                        <td className="numeric tabular" style={{ color: diff >= 0 ? "var(--accent)" : "var(--danger)" }}>
                          {diff >= 0 ? "+" : ""}{formatKRW(diff)}
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            )}
          </div>
        </div>
      </div>

      {/* Confirm modal */}
      <Modal open={previewOpen} onClose={closePreview} title={isLive ? "네이버에 일괄 가격 변경 적용" : "일괄 가격 수정 확인"}
             size="lg"
             footer={
               !saveProgress ? (
                 <>
                   <button className="btn" onClick={closePreview}>취소</button>
                   <button className="btn btn-primary" onClick={apply} disabled={previewRows.length === 0}>
                     <window.I.Check size={14} /> {previewRows.length}개 {isLive ? "네이버에 적용" : "가격 수정 적용"}
                   </button>
                 </>
               ) : naverSaving ? (
                 <button className="btn btn-danger" onClick={abortBulk}>
                   <window.I.X size={14} /> 중지 ({saveProgress.done}/{saveProgress.total})
                 </button>
               ) : (
                 <button className="btn btn-primary" onClick={closePreview}>닫기</button>
               )
             }>
        {!saveProgress ? (
          <>
            <div style={{ padding: "12px 14px", background: "var(--accent-soft)", borderRadius: 8, marginBottom: 12 }}>
              <div style={{ fontWeight: 600, marginBottom: 4 }}>
                {previewRows.length}개 상품의 가격이 변경됩니다 (실제 변경분만 표시 · 10원 단위 반올림)
              </div>
              <div className="text-sm muted">
                총 변동액: <strong className="tabular" style={{ color: totalDelta >= 0 ? "var(--accent)" : "var(--danger)" }}>
                  {totalDelta >= 0 ? "+" : ""}{formatKRW(totalDelta)}
                </strong>
              </div>
            </div>
            <div style={{
              padding: "10px 12px", borderRadius: 6, marginBottom: 12,
              background: isLive ? "rgba(245, 158, 11, 0.08)" : "var(--bg-elev)",
              border: isLive ? "1px solid rgba(245, 158, 11, 0.35)" : "1px solid var(--border)",
              fontSize: 12, color: "var(--text-muted)", display: "flex", gap: 8, alignItems: "flex-start"
            }}>
              <window.I.AlertCircle size={14} stroke={isLive ? "var(--warning)" : "currentColor"} style={{ flexShrink: 0, marginTop: 1 }} />
              <span>
                {isLive
                  ? <><strong style={{ color: "var(--text)" }}>주의:</strong> 적용은 즉시 네이버 스토어에 반영됩니다. 순차 처리되며 중간에 "중지" 가능하지만 이미 적용된 항목은 자동 원복되지 않습니다. (10원 단위 정규화)</>
                  : "이 작업은 되돌릴 수 없습니다. 변경 후에도 30일간 가격 변경 이력에서 확인 가능."}
              </span>
            </div>
            {previewRows.length > 0 && (
              <div style={{ maxHeight: 280, overflow: "auto", border: "1px solid var(--border)", borderRadius: 6 }}>
                <table className="table">
                  <thead>
                    <tr>
                      <th>상품</th>
                      <th className="numeric">현재가</th>
                      <th className="numeric">변경가</th>
                      <th className="numeric">차액</th>
                    </tr>
                  </thead>
                  <tbody>
                    {previewRows.slice(0, 50).map(p => {
                      const diff = p.newPrice - p.price;
                      const hasDiscount = p.discount > 0;
                      return (
                        <tr key={p.id}>
                          <td style={{ maxWidth: 320, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }} title={p.name}>
                            {p.name}
                            {hasDiscount && (
                              <div className="text-xs" style={{ color: "var(--accent)", marginTop: 1 }}>
                                할인가 {formatKRW(p.oldDiscountedPrice)} → {formatKRW(p.newDiscountedPrice)} (즉시할인 {formatNum(p.discount)}원 유지)
                              </div>
                            )}
                          </td>
                          <td className="numeric muted">{formatKRW(p.price)}</td>
                          <td className="numeric" style={{ fontWeight: 600 }}>{formatKRW(p.newPrice)}</td>
                          <td className="numeric tabular" style={{ color: diff >= 0 ? "var(--accent)" : "var(--danger)", fontSize: 12 }}>
                            {diff >= 0 ? "+" : ""}{formatKRW(diff)}
                          </td>
                        </tr>
                      );
                    })}
                    {previewRows.length > 50 && (
                      <tr><td colSpan="4" className="muted text-sm" style={{ textAlign: "center", padding: 10 }}>
                        ... 외 {previewRows.length - 50}개 (전체 적용됩니다)
                      </td></tr>
                    )}
                  </tbody>
                </table>
              </div>
            )}
          </>
        ) : (
          <>
            <div style={{ marginBottom: 12 }}>
              <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 6, fontSize: 13 }}>
                <span>{naverSaving ? "네이버에 적용 중..." : saveProgress.aborted ? "중지됨" : "완료"}</span>
                <span>{saveProgress.done} / {saveProgress.total}</span>
              </div>
              <div style={{ height: 8, background: "var(--border)", borderRadius: 4, overflow: "hidden" }}>
                <div style={{
                  height: "100%",
                  width: `${saveProgress.total ? (saveProgress.done / saveProgress.total * 100) : 0}%`,
                  background: "var(--accent)",
                  transition: "width 0.2s",
                }} />
              </div>
            </div>
            <div style={{ display: "flex", gap: 16, fontSize: 13, marginBottom: 12 }}>
              <span><strong style={{ color: "var(--success)" }}>{saveProgress.succeeded.length}</strong> 성공</span>
              <span><strong style={{ color: "var(--danger)" }}>{saveProgress.failed.length}</strong> 실패</span>
              {saveProgress.aborted && <span className="muted">· 사용자 중지</span>}
            </div>
            {saveProgress.failed.length > 0 && (
              <div style={{ marginTop: 8, padding: 10, background: "rgba(239, 68, 68, 0.05)", border: "1px solid rgba(239, 68, 68, 0.2)", borderRadius: 6, fontSize: 12, maxHeight: 200, overflow: "auto" }}>
                <div style={{ fontWeight: 600, marginBottom: 6 }}>실패 목록:</div>
                {saveProgress.failed.map(f => (
                  <div key={f.id} style={{ marginBottom: 6 }}>
                    <div style={{ color: "var(--text)" }}>{f.name}</div>
                    <div className="muted" style={{ paddingLeft: 8, fontSize: 11 }}>{f.error}</div>
                  </div>
                ))}
              </div>
            )}
          </>
        )}
      </Modal>
    </div>
  );
}

window.BulkEditScreen = BulkEditScreen;
