// shop-settings.jsx — 매장 정보 (P-02, 디렉터 권고 P3)
// ──────────────────────────────────────────────────────────────
// owner 전용. shop_settings 테이블 연동.
// D-03 매장 등기 정보 5종(상호/사업자번호/주소/대표전화/이메일) +
// 영업시간 · 정비실 운영시간 · 견적서 노출용 표기 등 등록.
// 입력값은 견적서 헤더 / 약관 / 도움말에서 재사용된다.
// ──────────────────────────────────────────────────────────────

const { useState, useEffect } = React;

// 기본 폼 스키마 (mock + 실 DB 공용)
const EMPTY = {
  // [필수] 등기/법적
  shop_name: "",       // 상호
  biz_no: "",          // 사업자등록번호
  ceo_name: "",        // 대표자명
  address: "",         // 사업장 주소
  phone: "",           // 대표 전화
  email: "",           // 대표 이메일
  // [선택] 견적서/약관 노출용
  shop_alias: "",      // 표기명 (예: "스페셜라이즈드 세종점")
  account_bank: "",    // 입금 계좌 은행
  account_no: "",      // 계좌번호
  account_holder: "",  // 예금주
  // 영업시간
  hours_open: "10:00",
  hours_close: "20:00",
  closed_days: "월요일",
  service_open: "10:00",
  service_close: "19:00",
};

function Header() {
  return (
    <header className="cat-header">
      <div className="cat-header-inner">
        <a className="cat-brand" href="관리자.html">
          <img className="cat-brand-mark" src="assets/symbol-brush.svg" alt="" />
          <div>
            <div className="cat-brand-name">스페셜라이즈드 세종점</div>
            <div className="cat-brand-sub">Admin · 매장 정보</div>
          </div>
        </a>
        <div className="cat-header-sep" />
        <div className="cat-header-title">매장 <b>정보</b></div>
        <div className="cat-header-tools">
          <span>견적서/약관 자동 채움 원천</span>
          {window.HeaderUser && React.createElement(window.HeaderUser)}
        </div>
      </div>
    </header>
  );
}

function PageNav() {
  return (
    <nav className="cat-pagenav">
      <div className="cat-pagenav-inner">
        <a href="관리자.html">관리자 <small>Admin</small></a>
        <a href="스케줄러.html">스케줄러 <small>Scheduler</small></a>
        <a href="2026 카탈로그.html">카탈로그 <small>Catalog</small></a>
        <a href="재고관리.html">재고관리 <small>Inventory</small></a>
        <a href="서비스 견적서.html">서비스 견적서 <small>Estimate</small></a>
        <a href="활동로그.html">활동 로그 <small>Activity</small></a>
        <a href="직원관리.html">직원 관리 <small>Staff</small></a>
        <a className="on" href="매장설정.html">🏪 매장 정보 <small>Shop</small></a>
      </div>
    </nav>
  );
}

function Forbidden() {
  return (
    <main className="adm-main">
      <div className="cat-inner" style={{padding:"60px 20px",textAlign:"center"}}>
        <div style={{fontSize:48,marginBottom:12}}>🔒</div>
        <h1 style={{margin:"0 0 8px",font:"700 24px/1.3 var(--font-sans)"}}>접근 권한이 없습니다</h1>
        <p style={{color:"var(--grey-600,#6B7684)",marginBottom:20}}>
          매장 정보는 사장님(owner) 전용입니다.
        </p>
        <a href="관리자.html" className="cat-print-btn" style={{display:"inline-block"}}>
          ← 대시보드로 돌아가기
        </a>
      </div>
    </main>
  );
}

// 입력 필드 공용
function Field({ label, name, value, onChange, required, placeholder, hint, type="text" }) {
  return (
    <label style={{display:"flex",flexDirection:"column",gap:6,fontSize:13}}>
      <span style={{color:"var(--grey-700,#4E5968)",fontWeight:500}}>
        {label}
        {required && <span style={{color:"var(--red-500,#E31E26)",marginLeft:4}}>*</span>}
      </span>
      <input
        type={type}
        name={name}
        value={value || ""}
        onChange={onChange}
        placeholder={placeholder}
        style={{
          padding:"10px 12px",border:"1px solid var(--grey-300,#D1D6DB)",
          borderRadius:8,fontSize:14,
        }}
      />
      {hint && <span style={{fontSize:12,color:"var(--grey-500,#8B95A1)"}}>{hint}</span>}
    </label>
  );
}

// 섹션 카드
function Section({ title, sub, children }) {
  return (
    <section style={{
      background:"#fff",border:"1px solid var(--grey-200,#E5E8EB)",
      borderRadius:12,padding:20,marginBottom:16,
    }}>
      <div style={{marginBottom:14}}>
        <div style={{font:"700 16px/1.3 var(--font-sans)"}}>{title}</div>
        {sub && <div style={{fontSize:12,color:"var(--grey-500,#8B95A1)",marginTop:4}}>{sub}</div>}
      </div>
      {children}
    </section>
  );
}

// v3.17: 텔레그램 알림 설정 섹션
function NotifySection() {
  const [s, setS] = useState({
    telegram_token: "", telegram_chat: "",
    flag_stock_in: true, flag_stock_out: true, flag_stock_move: false,
    flag_quote_new: true, flag_quote_ok: true, flag_staff_join: true,
    flag_low_stock: true, low_threshold: 2,
  });
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [testing, setTesting] = useState(false);
  const [msg, setMsg] = useState("");
  const [show, setShow] = useState(false); // 토큰 표시 토글

  useEffect(() => {
    (async () => {
      try {
        if (window.DAL?.client) {
          const { data } = await window.DAL.client.from("notify_settings").select("*").eq("id", 1).single();
          if (data) setS({...s, ...data});
        }
      } catch (e) { console.warn("[notify] load:", e); }
      finally { setLoading(false); }
    })();
  }, []);

  const change = (k, v) => setS(prev => ({...prev, [k]: v}));

  const save = async () => {
    setSaving(true); setMsg("");
    try {
      if (window.DAL?.client) {
        const { error } = await window.DAL.client.from("notify_settings").update({
          telegram_token: s.telegram_token || null,
          telegram_chat: s.telegram_chat || null,
          flag_stock_in: s.flag_stock_in, flag_stock_out: s.flag_stock_out,
          flag_stock_move: s.flag_stock_move, flag_quote_new: s.flag_quote_new,
          flag_quote_ok: s.flag_quote_ok, flag_staff_join: s.flag_staff_join,
          flag_low_stock: s.flag_low_stock, low_threshold: Number(s.low_threshold) || 2,
          updated_at: new Date().toISOString(),
        }).eq("id", 1);
        if (error) throw error;
      }
      setMsg("✓ 저장 완료");
      setTimeout(() => setMsg(""), 3000);
    } catch (e) {
      setMsg("⚠ 저장 실패: " + e.message);
    } finally { setSaving(false); }
  };

  const sendTest = async () => {
    setTesting(true); setMsg("");
    try {
      // 먼저 저장
      await save();
      // 테스트 발송
      if (window.DAL?.client) {
        const { error } = await window.DAL.client.rpc("notify_test");
        if (error) throw error;
      }
      setMsg("✓ 텔레그램 단톡방을 확인해주세요!");
    } catch (e) {
      setMsg("⚠ " + (e.message.includes("token_or_chat_missing") ? "봇 토큰과 chat_id를 먼저 입력해주세요" : "발송 실패: " + e.message));
    } finally { setTesting(false); }
  };

  const flags = [
    { k: "flag_stock_in",   label: "📦 입고 알림" },
    { k: "flag_stock_out",  label: "📤 출고 알림" },
    { k: "flag_stock_move", label: "🔄 위치 이동 알림" },
    { k: "flag_quote_new",  label: "🧾 견적 발행" },
    { k: "flag_quote_ok",   label: "✅ 견적 수락" },
    { k: "flag_staff_join", label: "👤 직원 가입 신청" },
    { k: "flag_low_stock",  label: "⚠️ 저재고 자동 경보" },
  ];

  if (loading) return null;

  return (
    <Section title="④ 🔔 텔레그램 알림 (선택)" sub="입출고·견적·가입 발생 시 매장 단톡방에 자동 메시지 발송. 봇 토큰과 chat_id 입력 후 테스트 발송으로 연결 확인하세요.">
      <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:14,marginBottom:14}}>
        <div style={{display:"flex",flexDirection:"column",gap:6}}>
          <label style={{fontSize:13,color:"var(--grey-700,#4E5968)",fontWeight:500}}>봇 토큰</label>
          <div style={{display:"flex",gap:4}}>
            <input type={show?"text":"password"} value={s.telegram_token || ""}
              onChange={e=>change("telegram_token", e.target.value)}
              placeholder="123456:ABC-DEF..." style={{flex:1,padding:"9px 11px",border:"1px solid var(--grey-300,#D1D6DB)",borderRadius:8,fontSize:13,fontFamily:"monospace"}}/>
            <button type="button" onClick={()=>setShow(!show)} style={{padding:"6px 10px",border:"1px solid var(--grey-300)",borderRadius:8,background:"#fff",cursor:"pointer",fontSize:12}}>{show?"숨김":"표시"}</button>
          </div>
          <small style={{fontSize:11,color:"var(--grey-500,#8B95A1)"}}>텔레그램 @BotFather → /newbot 으로 발급</small>
        </div>
        <div style={{display:"flex",flexDirection:"column",gap:6}}>
          <label style={{fontSize:13,color:"var(--grey-700,#4E5968)",fontWeight:500}}>단톡방 chat_id</label>
          <input value={s.telegram_chat || ""} onChange={e=>change("telegram_chat", e.target.value)}
            placeholder="-1001234567890 (그룹) 또는 123456789 (1:1)"
            style={{padding:"9px 11px",border:"1px solid var(--grey-300,#D1D6DB)",borderRadius:8,fontSize:13,fontFamily:"monospace"}}/>
          <small style={{fontSize:11,color:"var(--grey-500,#8B95A1)"}}>단톡방에 봇 + @userinfobot 추가 후 메시지 보내 확인</small>
        </div>
      </div>

      <div style={{padding:"12px 14px",background:"var(--grey-50,#F9FAFB)",borderRadius:8,marginBottom:14}}>
        <div style={{fontSize:12,color:"var(--grey-700,#4E5968)",fontWeight:600,marginBottom:8}}>알림 종류 (켜고 끌 수 있음)</div>
        <div style={{display:"grid",gridTemplateColumns:"repeat(3, 1fr)",gap:8}}>
          {flags.map(f => (
            <label key={f.k} style={{display:"flex",alignItems:"center",gap:6,fontSize:13,cursor:"pointer"}}>
              <input type="checkbox" checked={!!s[f.k]} onChange={e=>change(f.k, e.target.checked)} />
              <span>{f.label}</span>
            </label>
          ))}
          <label style={{display:"flex",alignItems:"center",gap:6,fontSize:12,color:"var(--grey-600,#6B7684)"}}>
            <span>저재고 기준 ≤</span>
            <input type="number" min="0" max="20" value={s.low_threshold || 2}
              onChange={e=>change("low_threshold", e.target.value)}
              style={{width:50,padding:"3px 6px",border:"1px solid var(--grey-300)",borderRadius:4,fontSize:12}}/>
            <span>대</span>
          </label>
        </div>
      </div>

      <div style={{display:"flex",gap:8,alignItems:"center"}}>
        <button onClick={save} disabled={saving} style={{padding:"8px 16px",border:"1px solid var(--grey-300)",borderRadius:8,background:"#fff",cursor:"pointer",fontSize:13}}>{saving?"저장 중...":"💾 설정 저장"}</button>
        <button onClick={sendTest} disabled={testing || !s.telegram_token || !s.telegram_chat}
          style={{padding:"8px 16px",border:"none",borderRadius:8,
            background:(testing || !s.telegram_token || !s.telegram_chat)?"var(--grey-300)":"var(--blue-500,#0064FF)",
            color:"#fff",cursor:(!s.telegram_token||!s.telegram_chat)?"not-allowed":"pointer",fontSize:13,fontWeight:600}}>
          {testing?"발송 중...":"🚀 테스트 발송"}
        </button>
        {msg && <span style={{fontSize:12, color: msg.startsWith("✓")?"var(--green-500,#0E8F5F)":"var(--red-500,#E31E26)"}}>{msg}</span>}
      </div>

      <div style={{marginTop:12,padding:"10px 12px",background:"var(--blue-50,#E8F3FF)",borderRadius:8,fontSize:12,color:"var(--blue-700,#0049BD)",lineHeight:1.6}}>
        💡 <b>5분 설정 가이드</b>: ① 텔레그램에서 <b>@BotFather</b> 검색 → <b>/newbot</b> 입력 → 봇 이름 지정 → 토큰 복사 · ② 매장 단톡방 만들고 봇 추가 · ③ 단톡방에 <b>@userinfobot</b> 추가해 chat_id 받기 (그룹은 -로 시작) · ④ 위 두 칸 입력 후 [🚀 테스트 발송]
      </div>
    </Section>
  );
}

// ──────────────────────────────────────────────────────────────────
// v3.23: CategoriesSection — 자전거 카테고리 동적 관리
// ──────────────────────────────────────────────────────────────────
function CategoriesSection() {
  const { useState, useEffect } = React;
  const [list, setList] = useState(window.CATEGORIES_LIST || []);
  const [editing, setEditing] = useState(null); // {key, name_ko, ...} 또는 null
  const [adding, setAdding] = useState(false);
  const [busy, setBusy] = useState(false);
  const [msg, setMsg] = useState("");

  // 초기 로드
  useEffect(() => {
    (async () => {
      try {
        if (window.loadCategories) await window.loadCategories(true);
        setList(window.CATEGORIES_LIST || []);
      } catch (e) { console.warn("[CategoriesSection] load:", e); }
    })();
    const handler = () => setList(window.CATEGORIES_LIST || []);
    window.addEventListener("categories:ready", handler);
    return () => window.removeEventListener("categories:ready", handler);
  }, []);

  const refresh = async () => {
    if (window.loadCategories) await window.loadCategories(true);
    setList(window.CATEGORIES_LIST || []);
  };

  const handleSave = async (data, isNew) => {
    setBusy(true);
    try {
      if (isNew) await window.DAL.createCategory(data);
      else await window.DAL.updateCategory(data.key, data);
      await refresh();
      setEditing(null); setAdding(false);
      setMsg(`✓ ${isNew ? "추가" : "수정"}되었습니다: ${data.name_ko}`);
      setTimeout(() => setMsg(""), 2500);
    } catch (e) {
      alert("저장 실패: " + e.message);
    } finally { setBusy(false); }
  };

  const handleDelete = async (cat) => {
    if (!confirm(`"${cat.name_ko}" 카테고리를 삭제하시겠습니까?\n\n사용 중인 자전거가 있으면 비활성화(숨김) 처리됩니다.`)) return;
    setBusy(true);
    try {
      await window.DAL.deleteCategory(cat.key);
      await refresh();
      setMsg(`🗑️ 삭제되었습니다: ${cat.name_ko}`);
      setTimeout(() => setMsg(""), 2500);
    } catch (e) { alert("삭제 실패: " + e.message); }
    finally { setBusy(false); }
  };

  return (
    <Section title="🚲 자전거 카테고리" subtitle="신상 등록 / 카탈로그 / 재고관리에서 사용하는 카테고리를 직접 추가·수정·삭제할 수 있습니다. 기본 5종은 그대로 두고 새 카테고리(예: 픽시, BMX)를 추가할 수 있습니다.">
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(220px,1fr))",gap:12}}>
        {list.map(c => (
          <div key={c.key} style={{
            background:"#fff",border:`2px solid ${c.color}22`,borderRadius:12,padding:14,
            transition:"transform .15s",
          }}>
            <div style={{display:"flex",alignItems:"center",gap:8,marginBottom:8}}>
              <span style={{
                width:36,height:36,borderRadius:18,
                background:c.color,color:"#fff",
                display:"flex",alignItems:"center",justifyContent:"center",
                fontSize:18,
              }}>{c.emoji}</span>
              <div style={{flex:1,minWidth:0}}>
                <div style={{fontSize:14,fontWeight:700,color:"var(--grey-900,#191F28)"}}>{c.name_ko}</div>
                <div style={{fontSize:11,color:"var(--grey-500,#8B95A1)"}}>{c.key} · 정렬 {c.sort_order}</div>
              </div>
            </div>
            {c.hint && <div style={{fontSize:11,color:"var(--grey-600,#6B7684)",marginBottom:10,minHeight:14}}>{c.hint}</div>}
            <div style={{display:"flex",gap:6}}>
              <button onClick={()=>setEditing(c)} disabled={busy} style={{flex:1,padding:"6px 10px",border:"1px solid var(--grey-300,#D1D6DB)",borderRadius:6,background:"#fff",cursor:"pointer",fontSize:12}}>수정</button>
              <button onClick={()=>handleDelete(c)} disabled={busy} style={{flex:1,padding:"6px 10px",border:"1px solid #FFCDD2",borderRadius:6,background:"#fff",color:"#9A0E14",cursor:"pointer",fontSize:12}}>삭제</button>
            </div>
          </div>
        ))}
        {/* + 새 카테고리 카드 */}
        <button onClick={()=>setAdding(true)} disabled={busy} style={{
          background:"transparent",border:"2px dashed var(--grey-300,#D1D6DB)",borderRadius:12,padding:14,
          cursor:"pointer",color:"var(--grey-600,#6B7684)",fontSize:13,minHeight:120,
          display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:6,
        }}>
          <span style={{fontSize:24}}>＋</span>
          <span>새 카테고리</span>
        </button>
      </div>

      {msg && (
        <div style={{marginTop:12,padding:"8px 12px",background:"#E6F7F0",color:"#0E8F5F",borderRadius:6,fontSize:13,fontWeight:600}}>
          {msg}
        </div>
      )}

      {(editing || adding) && (
        <CategoryEditModal
          init={editing}
          isNew={adding}
          onSave={handleSave}
          onClose={() => { setEditing(null); setAdding(false); }}
        />
      )}
    </Section>
  );
}

function CategoryEditModal({ init, isNew, onSave, onClose }) {
  const { useState } = React;
  const [form, setForm] = useState(init || {
    key: "", name_ko: "", name_en: "", emoji: "🚲", color: "#8B95A1", hint: "", sort_order: 100,
  });
  const upd = (patch) => setForm(f => ({ ...f, ...patch }));
  const canSave = form.key.trim() && form.name_ko.trim();

  const emojiOpts = ["🚴","🚵","⛰️","⚡","🧒","🚲","🛴","🏔️","🎯","⭐","🏁","🛞"];
  const colorOpts = ["#1B1B1F","#E31E26","#FF6B00","#FFB800","#0064FF","#3B82F6","#0E8F5F","#22C55E","#8B5CF6","#74777F"];

  return (
    <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.5)",zIndex:1000,display:"flex",alignItems:"center",justifyContent:"center",padding:16}} onClick={onClose}>
      <div onClick={e=>e.stopPropagation()} style={{background:"#fff",borderRadius:16,maxWidth:520,width:"100%",padding:24,boxShadow:"0 20px 60px rgba(0,0,0,0.2)",maxHeight:"90vh",overflow:"auto"}}>
        <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:16}}>
          <h2 style={{margin:0,font:"700 18px/1.3 var(--font-sans)"}}>
            {isNew ? "🆕 새 카테고리 추가" : `✏️ 카테고리 수정 — ${form.name_ko}`}
          </h2>
          <button onClick={onClose} style={{background:"none",border:"none",fontSize:22,cursor:"pointer",color:"#8B95A1"}}>×</button>
        </div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10,marginBottom:12}}>
          <div>
            <label style={{fontSize:12,fontWeight:600,color:"#4E5968",display:"block",marginBottom:4}}>키 (영문)*</label>
            <input value={form.key} disabled={!isNew} onChange={e=>upd({key:e.target.value.toLowerCase().replace(/[^a-z0-9_]/g,"")})} placeholder="fixie" style={{width:"100%",padding:"8px 10px",border:"1px solid #D1D6DB",borderRadius:6,fontSize:13,boxSizing:"border-box",background:isNew?"#fff":"#F2F4F6"}} />
            <small style={{fontSize:10,color:"#8B95A1"}}>{isNew ? "영문 소문자/숫자/언더스코어만" : "수정 불가"}</small>
          </div>
          <div>
            <label style={{fontSize:12,fontWeight:600,color:"#4E5968",display:"block",marginBottom:4}}>한글명*</label>
            <input value={form.name_ko} onChange={e=>upd({name_ko:e.target.value})} placeholder="픽시" style={{width:"100%",padding:"8px 10px",border:"1px solid #D1D6DB",borderRadius:6,fontSize:13,boxSizing:"border-box"}} />
          </div>
        </div>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:10,marginBottom:12}}>
          <div>
            <label style={{fontSize:12,fontWeight:600,color:"#4E5968",display:"block",marginBottom:4}}>영문 라벨</label>
            <input value={form.name_en||""} onChange={e=>upd({name_en:e.target.value})} placeholder="Fixie" style={{width:"100%",padding:"8px 10px",border:"1px solid #D1D6DB",borderRadius:6,fontSize:13,boxSizing:"border-box"}} />
          </div>
          <div>
            <label style={{fontSize:12,fontWeight:600,color:"#4E5968",display:"block",marginBottom:4}}>정렬 순서</label>
            <input type="number" value={form.sort_order} onChange={e=>upd({sort_order:Number(e.target.value)})} style={{width:"100%",padding:"8px 10px",border:"1px solid #D1D6DB",borderRadius:6,fontSize:13,boxSizing:"border-box"}} />
          </div>
        </div>
        <div style={{marginBottom:12}}>
          <label style={{fontSize:12,fontWeight:600,color:"#4E5968",display:"block",marginBottom:4}}>아이콘 (이모지)</label>
          <div style={{display:"flex",gap:6,flexWrap:"wrap"}}>
            {emojiOpts.map(e => (
              <button key={e} type="button" onClick={()=>upd({emoji:e})} style={{width:36,height:36,border:`2px solid ${form.emoji===e?"#0064FF":"#D1D6DB"}`,borderRadius:8,background:form.emoji===e?"#E8F3FF":"#fff",fontSize:18,cursor:"pointer"}}>{e}</button>
            ))}
            <input value={form.emoji} onChange={e=>upd({emoji:e.target.value})} maxLength={2} style={{width:60,padding:"8px 10px",border:"1px solid #D1D6DB",borderRadius:6,fontSize:18,textAlign:"center"}} />
          </div>
        </div>
        <div style={{marginBottom:12}}>
          <label style={{fontSize:12,fontWeight:600,color:"#4E5968",display:"block",marginBottom:4}}>색상</label>
          <div style={{display:"flex",gap:6,flexWrap:"wrap"}}>
            {colorOpts.map(c => (
              <button key={c} type="button" onClick={()=>upd({color:c})} style={{width:28,height:28,borderRadius:14,background:c,border:`3px solid ${form.color===c?"#191F28":"transparent"}`,cursor:"pointer"}} title={c} />
            ))}
          </div>
        </div>
        <div style={{marginBottom:18}}>
          <label style={{fontSize:12,fontWeight:600,color:"#4E5968",display:"block",marginBottom:4}}>부제 (선택)</label>
          <input value={form.hint||""} onChange={e=>upd({hint:e.target.value})} placeholder="예: 트랙 · 도시형 single speed" style={{width:"100%",padding:"8px 10px",border:"1px solid #D1D6DB",borderRadius:6,fontSize:13,boxSizing:"border-box"}} />
        </div>

        {/* 미리보기 */}
        <div style={{padding:"12px 14px",background:"#F9FAFB",borderRadius:8,marginBottom:16}}>
          <span style={{fontSize:11,color:"#8B95A1",marginBottom:6,display:"block",fontWeight:600}}>미리보기</span>
          <div style={{display:"inline-flex",alignItems:"center",gap:8,padding:"6px 12px",background:"#fff",borderRadius:8,border:`2px solid ${form.color}33`}}>
            <span style={{width:24,height:24,borderRadius:12,background:form.color,color:"#fff",display:"flex",alignItems:"center",justifyContent:"center",fontSize:13}}>{form.emoji}</span>
            <b style={{fontSize:13}}>{form.name_ko || "(미입력)"}</b>
            <small style={{color:"#8B95A1"}}>{form.hint}</small>
          </div>
        </div>

        <div style={{display:"flex",gap:8,justifyContent:"flex-end"}}>
          <button onClick={onClose} style={{padding:"10px 18px",border:"1px solid #D1D6DB",borderRadius:8,background:"#fff",cursor:"pointer",fontSize:14}}>취소</button>
          <button onClick={()=>onSave(form, isNew)} disabled={!canSave} style={{padding:"10px 20px",border:"none",borderRadius:8,background:canSave?"#0064FF":"#D1D6DB",color:"#fff",cursor:canSave?"pointer":"not-allowed",fontSize:14,fontWeight:600}}>
            {isNew ? "추가" : "저장"}
          </button>
        </div>
      </div>
    </div>
  );
}

function App() {
  const role = window.AUTH?.role || "owner";
  // RBAC v1.1: settings.edit 권한 체크
  const canEdit = window.AUTH?.can?.("settings.edit") ?? (role === "owner");
  const [form, setForm] = useState(EMPTY);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [savedAt, setSavedAt] = useState(null);
  const [errors, setErrors] = useState({});

  useEffect(() => {
    if (!canEdit) { setLoading(false); return; }
    let cancelled = false;
    async function load() {
      try {
        let data = null;
        if (window.DAL?.getShopSettings) {
          data = await window.DAL.getShopSettings();
        }
        // mock: localStorage 백업
        if (!data) {
          const raw = localStorage.getItem("sejong-shop-settings");
          if (raw) data = JSON.parse(raw);
        }
        if (!cancelled && data) setForm({ ...EMPTY, ...data });
      } catch (e) {
        console.warn("[shop-settings] load fail:", e);
      } finally {
        if (!cancelled) setLoading(false);
      }
    }
    load();
    return () => { cancelled = true; };
  }, [role]);

  const handleChange = (e) => {
    const { name, value } = e.target;
    setForm(prev => ({ ...prev, [name]: value }));
    if (errors[name]) setErrors(prev => ({ ...prev, [name]: null }));
  };

  const validate = () => {
    const e = {};
    if (!form.shop_name?.trim()) e.shop_name = "상호를 입력하세요";
    if (!form.biz_no?.trim()) e.biz_no = "사업자번호를 입력하세요";
    else if (!/^\d{3}-?\d{2}-?\d{5}$/.test(form.biz_no.replace(/-/g,""))) {
      e.biz_no = "사업자번호 형식이 올바르지 않습니다 (예: 123-45-67890)";
    }
    if (!form.address?.trim()) e.address = "주소를 입력하세요";
    if (!form.phone?.trim()) e.phone = "대표 전화를 입력하세요";
    if (form.email && !/^[^@]+@[^@]+\.[^@]+$/.test(form.email)) {
      e.email = "이메일 형식이 올바르지 않습니다";
    }
    setErrors(e);
    return Object.keys(e).length === 0;
  };

  const handleSave = async () => {
    if (!validate()) {
      // 첫 오류 필드로 스크롤
      const first = document.querySelector('input[name="' + Object.keys(errors)[0] + '"]');
      if (first) first.scrollIntoView({ behavior:"smooth", block:"center" });
      return;
    }
    setSaving(true);
    try {
      if (window.DAL?.saveShopSettings) {
        await window.DAL.saveShopSettings(form);
      }
      // 항상 localStorage 백업 (오프라인 대비)
      localStorage.setItem("sejong-shop-settings", JSON.stringify(form));
      setSavedAt(new Date());
    } catch (e) {
      alert("저장 실패: " + e.message);
    } finally {
      setSaving(false);
    }
  };

  if (role !== "owner") {
    return (
      <div className="cat-app">
        <Header /><PageNav />
        <Forbidden />
      </div>
    );
  }

  if (loading) {
    return (
      <div className="cat-app">
        <Header /><PageNav />
        <main className="adm-main">
          <div className="cat-inner" style={{padding:"60px 20px",textAlign:"center",color:"var(--grey-500,#8B95A1)"}}>
            불러오는 중...
          </div>
        </main>
      </div>
    );
  }

  const showErr = (name) => errors[name] && (
    <div style={{fontSize:12,color:"var(--red-500,#E31E26)",marginTop:4}}>⚠ {errors[name]}</div>
  );

  return (
    <div className="cat-app">
      <Header />
      <PageNav />
      <main className="adm-main">
        <div className="cat-inner">
          <div className="adm-page-head">
            <div>
              <h1>매장 정보</h1>
              <p>여기 입력한 값은 견적서 헤더 · 약관 페이지 · 도움말에 자동으로 들어갑니다. 처음 한 번만 채우면 됩니다.</p>
            </div>
            <div className="adm-page-head-tools">
              {savedAt && (
                <span style={{fontSize:12,color:"var(--green-700,#0E8F5F)"}}>
                  ✓ {savedAt.toLocaleTimeString("ko-KR")} 저장됨
                </span>
              )}
              <a href="관리자.html" className="cat-print-btn" style={{height:36,lineHeight:"36px"}}>
                ← 대시보드
              </a>
            </div>
          </div>

          <Section title="① 등기 · 법적 정보 (필수)" sub="전자상거래법상 견적서/이용약관에 반드시 표기해야 합니다.">
            <div style={{display:"grid",gridTemplateColumns:"repeat(2, 1fr)",gap:14}}>
              <div>
                <Field label="상호" name="shop_name" value={form.shop_name} onChange={handleChange}
                  required placeholder="예: (주)스페셜라이즈드코리아 세종점" />
                {showErr("shop_name")}
              </div>
              <div>
                <Field label="대표자명" name="ceo_name" value={form.ceo_name} onChange={handleChange}
                  placeholder="예: 김성호" />
              </div>
              <div>
                <Field label="사업자등록번호" name="biz_no" value={form.biz_no} onChange={handleChange}
                  required placeholder="123-45-67890" />
                {showErr("biz_no")}
              </div>
              <div>
                <Field label="대표 전화" name="phone" value={form.phone} onChange={handleChange}
                  required placeholder="044-000-0000" type="tel" />
                {showErr("phone")}
              </div>
              <div style={{gridColumn:"1 / -1"}}>
                <Field label="사업장 주소" name="address" value={form.address} onChange={handleChange}
                  required placeholder="세종특별자치시 ..." />
                {showErr("address")}
              </div>
              <div>
                <Field label="대표 이메일" name="email" value={form.email} onChange={handleChange}
                  placeholder="contact@example.com" type="email" />
                {showErr("email")}
              </div>
              <div>
                <Field label="견적서 표기명" name="shop_alias" value={form.shop_alias} onChange={handleChange}
                  placeholder="예: 스페셜라이즈드 세종점"
                  hint="견적서/카탈로그 헤더에 노출됩니다." />
              </div>
            </div>
          </Section>

          <Section title="② 입금 계좌 정보 (선택)" sub="견적서 하단 '결제 안내' 영역에 자동으로 표기됩니다.">
            <div style={{display:"grid",gridTemplateColumns:"repeat(3, 1fr)",gap:14}}>
              <Field label="은행" name="account_bank" value={form.account_bank} onChange={handleChange}
                placeholder="예: 신한은행" />
              <Field label="계좌번호" name="account_no" value={form.account_no} onChange={handleChange}
                placeholder="000-000-000000" />
              <Field label="예금주" name="account_holder" value={form.account_holder} onChange={handleChange}
                placeholder="예: (주)스페셜라이즈드코리아" />
            </div>
          </Section>

          <Section title="③ 영업시간" sub="고객 안내 · 스케줄러 가용 슬롯 계산에 사용됩니다.">
            <div style={{display:"grid",gridTemplateColumns:"repeat(3, 1fr)",gap:14}}>
              <Field label="매장 오픈" name="hours_open" value={form.hours_open} onChange={handleChange} type="time" />
              <Field label="매장 마감" name="hours_close" value={form.hours_close} onChange={handleChange} type="time" />
              <Field label="정기 휴무일" name="closed_days" value={form.closed_days} onChange={handleChange}
                placeholder="예: 월요일" />
              <Field label="정비실 오픈" name="service_open" value={form.service_open} onChange={handleChange} type="time" />
              <Field label="정비실 마감" name="service_close" value={form.service_close} onChange={handleChange} type="time" />
            </div>
          </Section>

          {/* v3.17: 텔레그램 알림 설정 */}
          <NotifySection />

          {/* v3.23: 자전거 카테고리 동적 관리 */}
          <CategoriesSection />

          {/* 저장 영역 */}
          <div style={{
            position:"sticky",bottom:16,
            display:"flex",justifyContent:"flex-end",gap:8,
            padding:"12px 16px",background:"#fff",
            border:"1px solid var(--grey-200,#E5E8EB)",borderRadius:12,
            boxShadow:"0 4px 16px rgba(0,0,0,0.04)",
          }}>
            <span style={{flex:1,fontSize:12,color:"var(--grey-500,#8B95A1)",alignSelf:"center"}}>
              * 필수 항목을 모두 입력해야 저장됩니다.
            </span>
            <button onClick={handleSave} disabled={saving} style={{
              padding:"10px 24px",border:"none",borderRadius:8,
              background:"var(--red-500,#E31E26)",color:"#fff",
              cursor: saving?"wait":"pointer",fontSize:14,fontWeight:600,
              opacity: saving?0.6:1,
            }}>{saving ? "저장 중..." : "💾 저장"}</button>
          </div>
        </div>
      </main>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
