// Admin Data Management — Excel upload, image/text management, IndexedDB persistence

// ═══════════════════════════════════════════════════════════
// IndexedDB Helper
// ═══════════════════════════════════════════════════════════
const WU_DB_NAME = 'workup-admin';
const WU_DB_VERSION = 1;

function openDB() {
  return new Promise((resolve, reject) => {
    const req = indexedDB.open(WU_DB_NAME, WU_DB_VERSION);
    req.onupgradeneeded = (e) => {
      const db = e.target.result;
      if (!db.objectStoreNames.contains('products')) db.createObjectStore('products', { keyPath: 'id', autoIncrement: true });
      if (!db.objectStoreNames.contains('stores')) db.createObjectStore('stores', { keyPath: 'id', autoIncrement: true });
      if (!db.objectStoreNames.contains('images')) db.createObjectStore('images', { keyPath: 'id', autoIncrement: true });
      if (!db.objectStoreNames.contains('settings')) db.createObjectStore('settings', { keyPath: 'key' });
    };
    req.onsuccess = () => resolve(req.result);
    req.onerror = () => reject(req.error);
  });
}

async function dbGetAll(storeName) {
  const db = await openDB();
  return new Promise((resolve, reject) => {
    const tx = db.transaction(storeName, 'readonly');
    const store = tx.objectStore(storeName);
    const req = store.getAll();
    req.onsuccess = () => resolve(req.result);
    req.onerror = () => reject(req.error);
  });
}

async function dbPut(storeName, data) {
  const db = await openDB();
  return new Promise((resolve, reject) => {
    const tx = db.transaction(storeName, 'readwrite');
    const store = tx.objectStore(storeName);
    const req = store.put(data);
    req.onsuccess = () => resolve(req.result);
    req.onerror = () => reject(req.error);
  });
}

async function dbPutBulk(storeName, items) {
  const db = await openDB();
  return new Promise((resolve, reject) => {
    const tx = db.transaction(storeName, 'readwrite');
    const store = tx.objectStore(storeName);
    store.clear();
    items.forEach(item => store.put(item));
    tx.oncomplete = () => resolve();
    tx.onerror = () => reject(tx.error);
  });
}

async function dbDelete(storeName, id) {
  const db = await openDB();
  return new Promise((resolve, reject) => {
    const tx = db.transaction(storeName, 'readwrite');
    const store = tx.objectStore(storeName);
    const req = store.delete(id);
    req.onsuccess = () => resolve();
    req.onerror = () => reject(req.error);
  });
}

async function dbClear(storeName) {
  const db = await openDB();
  return new Promise((resolve, reject) => {
    const tx = db.transaction(storeName, 'readwrite');
    tx.objectStore(storeName).clear();
    tx.oncomplete = () => resolve();
    tx.onerror = () => reject(tx.error);
  });
}

// File to base64
function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// Excel parser using SheetJS
async function parseExcel(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      try {
        const data = new Uint8Array(e.target.result);
        const wb = XLSX.read(data, { type: 'array' });
        const sheets = {};
        wb.SheetNames.forEach(name => {
          sheets[name] = XLSX.utils.sheet_to_json(wb.Sheets[name]);
        });
        resolve(sheets);
      } catch (err) { reject(err); }
    };
    reader.onerror = reject;
    reader.readAsArrayBuffer(file);
  });
}

Object.assign(window, { WU_DB_NAME, WU_DB_VERSION, openDB, dbGetAll, dbPut, dbPutBulk, dbDelete, dbClear, fileToBase64, parseExcel });

// ═══════════════════════════════════════════════════════════
// Admin Dashboard Component
// ═══════════════════════════════════════════════════════════
function AdminDashboard({ onBack }) {
  const [tab, setTab] = React.useState('products');
  const [products, setProducts] = React.useState([]);
  const [stores, setStores] = React.useState([]);
  const [images, setImages] = React.useState([]);
  const [uploading, setUploading] = React.useState(false);
  const [msg, setMsg] = React.useState(null);
  const [stats, setStats] = React.useState({ products: 0, stores: 0, images: 0 });

  // Load from IndexedDB on mount
  React.useEffect(() => {
    (async () => {
      const [p, s, i] = await Promise.all([dbGetAll('products'), dbGetAll('stores'), dbGetAll('images')]);
      setProducts(p); setStores(s); setImages(i);
      setStats({ products: p.length, stores: s.length, images: i.length });
    })();
  }, []);

  const flash = (text, type = 'ok') => { setMsg({ text, type }); setTimeout(() => setMsg(null), 3000); };

  // ── Excel Upload ──
  const handleExcelUpload = async (e, target) => {
    const file = e.target.files[0];
    if (!file) return;
    setUploading(true);
    try {
      const sheets = await parseExcel(file);
      const sheetName = Object.keys(sheets)[0];
      const rows = sheets[sheetName];
      if (!rows || rows.length === 0) { flash('빈 시트입니다', 'err'); setUploading(false); return; }

      const withId = rows.map((r, i) => ({ ...r, id: r.id || r.store_id || r.product_id || (i + 1) }));

      if (target === 'products') {
        await dbPutBulk('products', withId);
        setProducts(withId);
        setStats(s => ({ ...s, products: withId.length }));
        flash(`상품 ${withId.length}건 업로드 완료`);
      } else {
        await dbPutBulk('stores', withId);
        setStores(withId);
        setStats(s => ({ ...s, stores: withId.length }));
        flash(`매장 ${withId.length}건 업로드 완료`);
      }
    } catch (err) {
      flash('파싱 실패: ' + err.message, 'err');
    }
    setUploading(false);
    e.target.value = '';
  };

  // ── Image Upload ──
  const handleImageUpload = async (e) => {
    const files = Array.from(e.target.files);
    if (!files.length) return;
    setUploading(true);
    const newImages = [];
    for (const f of files) {
      const b64 = await fileToBase64(f);
      const entry = { id: Date.now() + Math.random(), name: f.name, data: b64, description: '', uploadedAt: new Date().toISOString() };
      await dbPut('images', entry);
      newImages.push(entry);
    }
    const all = [...images, ...newImages];
    setImages(all);
    setStats(s => ({ ...s, images: all.length }));
    flash(`이미지 ${files.length}건 업로드 완료`);
    setUploading(false);
    e.target.value = '';
  };

  // ── Image description update ──
  const updateImageDesc = async (id, desc) => {
    const img = images.find(i => i.id === id);
    if (!img) return;
    const updated = { ...img, description: desc };
    await dbPut('images', updated);
    setImages(images.map(i => i.id === id ? updated : i));
  };

  // ── Delete handlers ──
  const deleteImage = async (id) => {
    await dbDelete('images', id);
    const all = images.filter(i => i.id !== id);
    setImages(all);
    setStats(s => ({ ...s, images: all.length }));
    flash('이미지 삭제됨');
  };

  const clearStore = async (storeName) => {
    await dbClear(storeName);
    if (storeName === 'products') { setProducts([]); setStats(s => ({ ...s, products: 0 })); }
    if (storeName === 'stores') { setStores([]); setStats(s => ({ ...s, stores: 0 })); }
    if (storeName === 'images') { setImages([]); setStats(s => ({ ...s, images: 0 })); }
    flash(`${storeName} 데이터 초기화됨`);
  };

  React.useEffect(() => {
    const esc = e => { if (e.key === 'Escape') onBack(); };
    document.addEventListener('keydown', esc);
    return () => document.removeEventListener('keydown', esc);
  }, [onBack]);

  const tabs = [
    ['products', '📦 상품 관리'],
    ['stores', '🏪 매장 데이터'],
    ['images', '📷 이미지 관리'],
    ['kpi', '📊 실시간 KPI'],
  ];

  return (
    <div className="wu" style={{ height: '100vh', width: '100vw', display: 'flex', background: 'var(--wu-bg)' }}>
      {/* Sidebar */}
      <div style={{ width: 220, background: 'var(--wu-ink)', color: 'var(--wu-paper)', padding: '24px 18px', display: 'flex', flexDirection: 'column', flexShrink: 0 }}>
        <button onClick={onBack} style={{ cursor: 'pointer', background: 'none', textAlign: 'left' }}>
          <WuLogo size={22} color="var(--wu-paper)" />
        </button>
        <div className="mono" style={{ fontSize: 9, color: 'var(--wu-orange)', marginTop: 6, letterSpacing: '0.1em' }}>⚙ DATA ADMIN</div>

        <div style={{ marginTop: 28, display: 'flex', flexDirection: 'column', gap: 2 }}>
          {tabs.map(([k, l]) => (
            <button key={k} onClick={() => setTab(k)} className="kr" style={{ padding: '10px 12px', borderRadius: 6, textAlign: 'left', background: tab === k ? 'var(--wu-lime)' : 'transparent', color: tab === k ? 'var(--wu-ink)' : '#B8B3A8', cursor: 'pointer', fontSize: 12, fontWeight: 600 }}>{l}</button>
          ))}
        </div>

        {/* Quick stats */}
        <div style={{ marginTop: 'auto', padding: 12, background: '#1A1A17', borderRadius: 4 }}>
          <div className="mono" style={{ fontSize: 9, color: 'var(--wu-lime)' }}>● INDEXED DB</div>
          {[['상품', stats.products], ['매장', stats.stores], ['이미지', stats.images]].map(([l, n]) => (
            <div key={l} style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0' }}>
              <span className="kr" style={{ fontSize: 11, color: 'var(--wu-mute)' }}>{l}</span>
              <span className="mono" style={{ fontSize: 12, fontWeight: 700, color: 'var(--wu-paper)' }}>{n}</span>
            </div>
          ))}
        </div>
        <button onClick={onBack} className="mono" style={{ marginTop: 10, fontSize: 10, color: 'var(--wu-mute)', cursor: 'pointer', textAlign: 'left' }}>← 역할 전환 (ESC)</button>
      </div>

      {/* Content */}
      <div style={{ flex: 1, minWidth: 0, overflow: 'auto', position: 'relative' }} className="wu-scroll">
        {/* Flash message */}
        {msg && (
          <div style={{ position: 'fixed', top: 16, right: 16, zIndex: 999, padding: '10px 18px', background: msg.type === 'ok' ? 'var(--wu-lime)' : 'var(--wu-orange)', color: msg.type === 'ok' ? 'var(--wu-ink)' : '#fff', fontFamily: 'Pretendard', fontSize: 13, fontWeight: 700, boxShadow: '0 8px 24px rgba(0,0,0,0.2)' }}>
            {msg.text}
          </div>
        )}

        {uploading && (
          <div style={{ position: 'fixed', top: 0, left: 0, right: 0, height: 3, background: 'var(--wu-lime)', zIndex: 999, animation: 'wu-ticker 1s linear infinite' }} />
        )}

        {/* ── PRODUCTS TAB — direct input, not excel ── */}
        {tab === 'products' && (
          <AdminProductManager onBack={onBack} />
        )}

        {/* ── STORES TAB ── */}
        {tab === 'stores' && (
          <div style={{ padding: 28 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
              <div>
                <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>DATA ADMIN · STORES</div>
                <div className="display" style={{ fontSize: 28, marginTop: 2 }}>매장 데이터 관리</div>
                <div className="kr" style={{ fontSize: 12, color: 'var(--wu-mute)', marginTop: 4 }}>매장 정보 엑셀 템플릿에 맞춰 업로드하세요.</div>
              </div>
              <div style={{ display: 'flex', gap: 6 }}>
                <label className="wu-btn lime" style={{ fontSize: 11, padding: '8px 14px', cursor: 'pointer' }}>
                  📤 매장 엑셀 업로드
                  <input type="file" accept=".xlsx,.xls,.csv" onChange={e => handleExcelUpload(e, 'stores')} style={{ display: 'none' }} />
                </label>
                {stores.length > 0 && <button onClick={() => clearStore('stores')} className="wu-btn ghost" style={{ fontSize: 11, padding: '8px 14px', color: '#C44', borderColor: '#C44' }}>🗑 초기화</button>}
              </div>
            </div>

            <div style={{ marginTop: 16, background: 'var(--wu-ink)', color: 'var(--wu-paper)', padding: 16 }}>
              <div className="mono" style={{ fontSize: 10, color: 'var(--wu-lime)' }}>EXPECTED COLUMNS</div>
              <div className="mono" style={{ fontSize: 11, color: 'var(--wu-mute)', marginTop: 6, lineHeight: 1.8 }}>
                store_id · store_name · owner_name · region · city · address_road · latitude · longitude · hours_weekday · status · membership_status
              </div>
            </div>

            {stores.length > 0 ? (
              <div style={{ marginTop: 16, background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', overflow: 'auto' }}>
                <div style={{ display: 'grid', gridTemplateColumns: '60px 120px 100px 100px 1fr 100px 80px', padding: '10px 16px', fontFamily: 'JetBrains Mono', fontSize: 9, color: 'var(--wu-mute)', background: 'var(--wu-bg)', borderBottom: '1px solid var(--wu-line)', minWidth: 700 }}>
                  <div>#</div><div>매장명</div><div>점주</div><div>지역</div><div>주소</div><div>영업시간</div><div>상태</div>
                </div>
                {stores.slice(0, 50).map((s, i) => (
                  <div key={i} style={{ display: 'grid', gridTemplateColumns: '60px 120px 100px 100px 1fr 100px 80px', padding: '10px 16px', borderBottom: '1px solid var(--wu-line)', fontSize: 12, alignItems: 'center', minWidth: 700 }}>
                    <div className="mono" style={{ color: 'var(--wu-mute)' }}>{i + 1}</div>
                    <div className="kr" style={{ fontWeight: 700 }}>{s.store_name || s['매장명'] || '—'}</div>
                    <div className="kr">{s.owner_name || s['점주'] || '—'}</div>
                    <div className="kr" style={{ fontSize: 11, color: 'var(--wu-mute)' }}>{s.region || s['지역'] || '—'}</div>
                    <div className="kr" style={{ fontSize: 11, color: 'var(--wu-mute)' }}>{s.address_road || s['주소'] || '—'}</div>
                    <div className="mono" style={{ fontSize: 10 }}>{s.hours_weekday || s['영업시간'] || '—'}</div>
                    <span className="mono" style={{ fontSize: 9, padding: '2px 6px', fontWeight: 700, background: (s.status || '') === 'OPEN' ? 'var(--wu-lime)' : 'var(--wu-orange)', color: (s.status || '') === 'OPEN' ? 'var(--wu-ink)' : '#fff', width: 'fit-content' }}>{s.status || s['상태'] || '—'}</span>
                  </div>
                ))}
                {stores.length > 50 && <div className="mono" style={{ padding: 14, textAlign: 'center', color: 'var(--wu-mute)', fontSize: 11 }}>… 총 {stores.length}건</div>}
              </div>
            ) : (
              <div style={{ marginTop: 16, padding: '60px 20px', background: 'var(--wu-paper)', border: '2px dashed var(--wu-line)', textAlign: 'center' }}>
                <div style={{ fontSize: 40, marginBottom: 12 }}>🏪</div>
                <div className="display" style={{ fontSize: 18, color: 'var(--wu-mute)' }}>NO DATA</div>
                <div className="kr" style={{ fontSize: 12, color: 'var(--wu-mute)', marginTop: 6 }}>매장 엑셀 파일을 업로드해주세요</div>
              </div>
            )}
          </div>
        )}

        {/* ── IMAGES TAB ── */}
        {tab === 'images' && (
          <div style={{ padding: 28 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
              <div>
                <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>DATA ADMIN · IMAGES</div>
                <div className="display" style={{ fontSize: 28, marginTop: 2 }}>이미지 · 텍스트 관리</div>
                <div className="kr" style={{ fontSize: 12, color: 'var(--wu-mute)', marginTop: 4 }}>상품/매장 이미지를 업로드하고 설명을 추가하세요. IndexedDB에 저장됩니다.</div>
              </div>
              <div style={{ display: 'flex', gap: 6 }}>
                <label className="wu-btn lime" style={{ fontSize: 11, padding: '8px 14px', cursor: 'pointer' }}>
                  📷 이미지 업로드 (복수 가능)
                  <input type="file" accept="image/*" multiple onChange={handleImageUpload} style={{ display: 'none' }} />
                </label>
                {images.length > 0 && <button onClick={() => clearStore('images')} className="wu-btn ghost" style={{ fontSize: 11, padding: '8px 14px', color: '#C44', borderColor: '#C44' }}>🗑 전체 삭제</button>}
              </div>
            </div>

            {images.length > 0 ? (
              <div style={{ marginTop: 16, display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: 14 }}>
                {images.map(img => (
                  <div key={img.id} style={{ background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', overflow: 'hidden' }}>
                    <div style={{ position: 'relative' }}>
                      <img src={img.data} style={{ width: '100%', height: 200, objectFit: 'cover', display: 'block' }} />
                      <button onClick={() => deleteImage(img.id)} style={{ position: 'absolute', top: 8, right: 8, width: 28, height: 28, borderRadius: 999, background: 'rgba(0,0,0,0.7)', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 14, cursor: 'pointer', border: 0 }}>✕</button>
                    </div>
                    <div style={{ padding: 12 }}>
                      <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{img.name}</div>
                      <div className="mono" style={{ fontSize: 9, color: 'var(--wu-mute)', marginTop: 2 }}>{new Date(img.uploadedAt).toLocaleString('ko-KR')}</div>
                      <textarea
                        defaultValue={img.description}
                        placeholder="이미지 설명을 입력하세요 (상품명, 용도 등)"
                        onBlur={e => updateImageDesc(img.id, e.target.value)}
                        className="kr"
                        rows={2}
                        style={{ width: '100%', marginTop: 8, border: '1px solid var(--wu-line)', background: 'var(--wu-bg)', padding: 8, fontSize: 12, fontFamily: 'Pretendard', lineHeight: 1.5, resize: 'none', outline: 0 }}
                      />
                    </div>
                  </div>
                ))}
              </div>
            ) : (
              <div style={{ marginTop: 16, padding: '60px 20px', background: 'var(--wu-paper)', border: '2px dashed var(--wu-line)', textAlign: 'center' }}>
                <div style={{ fontSize: 40, marginBottom: 12 }}>📷</div>
                <div className="display" style={{ fontSize: 18, color: 'var(--wu-mute)' }}>NO IMAGES</div>
                <div className="kr" style={{ fontSize: 12, color: 'var(--wu-mute)', marginTop: 6 }}>이미지를 업로드해주세요 (JPG, PNG 등)</div>
              </div>
            )}
          </div>
        )}

        {/* ── KPI TAB ── */}
        {tab === 'kpi' && (
          <div style={{ padding: 28 }}>
            <div className="mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>DATA ADMIN · LIVE KPI</div>
            <div className="display" style={{ fontSize: 28, marginTop: 2 }}>실시간 데이터 KPI</div>
            <div className="kr" style={{ fontSize: 12, color: 'var(--wu-mute)', marginTop: 4 }}>업로드된 데이터에서 자동 집계한 지표입니다.</div>

            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12, marginTop: 20 }}>
              {[
                ['등록 상품', stats.products, '건', 'var(--wu-lime)'],
                ['등록 매장', stats.stores, '곳', 'var(--wu-orange)'],
                ['이미지 자산', stats.images, '장', '#fff'],
                ['브랜드 수', [...new Set(products.map(p => p.brand || p.BRAND).filter(Boolean))].length, '개', 'var(--wu-lime)'],
              ].map(([l, v, u, c]) => (
                <div key={l} style={{ background: 'var(--wu-ink)', padding: 20, color: 'var(--wu-paper)' }}>
                  <div className="kr mono" style={{ fontSize: 10, color: 'var(--wu-mute)' }}>{l}</div>
                  <div className="display" style={{ fontSize: 36, color: c, marginTop: 6 }}>{v}<span className="mono" style={{ fontSize: 12, color: 'var(--wu-mute)', marginLeft: 4 }}>{u}</span></div>
                </div>
              ))}
            </div>

            {/* Brand breakdown */}
            {products.length > 0 && (() => {
              const brandMap = {};
              products.forEach(p => {
                const b = p.brand || p.BRAND || 'UNKNOWN';
                brandMap[b] = (brandMap[b] || 0) + 1;
              });
              const sorted = Object.entries(brandMap).sort((a, b) => b[1] - a[1]);
              return (
                <div style={{ marginTop: 20, background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', padding: 20 }}>
                  <div className="display" style={{ fontSize: 18 }}>브랜드별 상품 수</div>
                  <div style={{ marginTop: 14 }}>
                    {sorted.map(([b, n]) => {
                      const pct = Math.round(n / products.length * 100);
                      return (
                        <div key={b} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '8px 0', borderBottom: '1px solid var(--wu-line)' }}>
                          <div className="mono" style={{ width: 120, fontSize: 11, fontWeight: 700, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{b}</div>
                          <div style={{ flex: 1, height: 16, background: 'var(--wu-bg)', position: 'relative' }}>
                            <div style={{ width: pct + '%', height: '100%', background: 'var(--wu-lime)' }} />
                          </div>
                          <div className="mono" style={{ width: 60, fontSize: 11, textAlign: 'right' }}>{n}건 ({pct}%)</div>
                        </div>
                      );
                    })}
                  </div>
                </div>
              );
            })()}

            {/* Region breakdown for stores */}
            {stores.length > 0 && (() => {
              const regionMap = {};
              stores.forEach(s => {
                const r = s.region || s['지역'] || 'UNKNOWN';
                regionMap[r] = (regionMap[r] || 0) + 1;
              });
              const sorted = Object.entries(regionMap).sort((a, b) => b[1] - a[1]);
              return (
                <div style={{ marginTop: 16, background: 'var(--wu-paper)', border: '1px solid var(--wu-line)', padding: 20 }}>
                  <div className="display" style={{ fontSize: 18 }}>지역별 매장 수</div>
                  <div style={{ marginTop: 14 }}>
                    {sorted.map(([r, n]) => {
                      const pct = Math.round(n / stores.length * 100);
                      return (
                        <div key={r} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '8px 0', borderBottom: '1px solid var(--wu-line)' }}>
                          <div className="kr" style={{ width: 100, fontSize: 12, fontWeight: 700 }}>{r}</div>
                          <div style={{ flex: 1, height: 16, background: 'var(--wu-bg)', position: 'relative' }}>
                            <div style={{ width: pct + '%', height: '100%', background: 'var(--wu-orange)' }} />
                          </div>
                          <div className="mono" style={{ width: 60, fontSize: 11, textAlign: 'right' }}>{n}곳 ({pct}%)</div>
                        </div>
                      );
                    })}
                  </div>
                </div>
              );
            })()}
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { AdminDashboard });
