// quotes-list.jsx — 견적서 목록 (v3.16 — DAL 통합, 모든 직원 조회)
const { useState, useMemo, useEffect } = React;

// 초기값: window.QUOTES_LIST가 비어 있어도 후속 useEffect에서 DAL.listQuotes로 채움
const QL_INITIAL = Array.isArray(window.QUOTES_LIST) ? window.QUOTES_LIST : [];
const fmtKRW = (n) => "₩" + n.toLocaleString("ko-KR");

function Header({ total }) {
  return (
    <header className="cat-header">
      <div className="cat-header-inner">
        <a className="cat-brand" href="#">
          <img className="cat-brand-mark" src="assets/symbol-brush.svg" alt="" />
          <div>
            <div className="cat-brand-name">스페셜라이즈드 세종점</div>
            <div className="cat-brand-sub">Quotes · 견적서 목록</div>
          </div>
        </a>
        <div className="cat-header-sep" />
        <div className="cat-header-title">견적서 <b>목록</b></div>
        <div className="cat-header-tools">
          <span>전체 <b>{total}</b>건</span>
        </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 className="on" href="견적서목록.html">견적서 <small>Quotes</small></a>
        <a href="서비스 견적서.html">새 견적서 <small>New</small></a>
      </div>
    </nav>
  );
}

function KpiStrip({ list }) {
  const total = list.reduce((a, b) => a + b.total, 0);
  const pending = list.filter(q => q.status === "대기").length;
  const approved = list.filter(q => q.status === "승인").length;
  const expired = list.filter(q => q.status === "만료").length;
  const avg = list.length ? Math.round(total / list.length) : 0;
  return (
    <div className="inv-kpi">
      <div className="inv-kpi-cell">
        <div className="inv-kpi-l">전체 견적</div>
        <div className="inv-kpi-v">{list.length}<small>건</small></div>
        <div className="inv-kpi-hint">최근 7일 기준</div>
      </div>
      <div className="inv-kpi-cell">
        <div className="inv-kpi-l">대기</div>
        <div className={"inv-kpi-v " + (pending ? "warn":"")}>{pending}<small>건</small></div>
        <div className="inv-kpi-hint">고객 응답 대기</div>
      </div>
      <div className="inv-kpi-cell">
        <div className="inv-kpi-l">승인</div>
        <div className="inv-kpi-v">{approved}<small>건</small></div>
        <div className="inv-kpi-hint">진행 중 / 결제 완료</div>
      </div>
      <div className="inv-kpi-cell">
        <div className="inv-kpi-l">만료</div>
        <div className={"inv-kpi-v " + (expired ? "err":"")}>{expired}<small>건</small></div>
        <div className="inv-kpi-hint">14일 경과</div>
      </div>
      <div className="inv-kpi-cell">
        <div className="inv-kpi-l">평균 견적가</div>
        <div className="inv-kpi-v">{fmtKRW(avg)}</div>
        <div className="inv-kpi-hint">최근 12건 평균</div>
      </div>
    </div>
  );
}

const STATUS_OPTIONS = [
  { id: "all",     label: "전체" },
  { id: "대기",    label: "대기" },
  { id: "승인",    label: "승인" },
  { id: "발송",    label: "발송" },
  { id: "만료",    label: "만료" },
];

// v3.11: 응답 대기 시간 계산 (발행일 → 현재)
function waitingHours(dateStr) {
  if (!dateStr) return 0;
  const d = new Date(dateStr);
  return Math.floor((Date.now() - d.getTime()) / 3600_000);
}

// v3.11: 인라인 상태 변경 드롭다운
function StatusDropdown({ value, onChange }) {
  const [open, setOpen] = React.useState(false);
  const options = [
    { id:"대기", tone:"amber" },
    { id:"승인", tone:"green" },
    { id:"발송", tone:"blue" },
    { id:"만료", tone:"red" },
  ];
  const current = options.find(o => o.id === value) || options[0];
  return (
    <div style={{position:"relative",display:"inline-block"}}>
      <button onClick={()=>setOpen(!open)}
        className={"adm-tag " + current.tone}
        style={{border:0,cursor:"pointer",padding:"4px 10px",display:"inline-flex",alignItems:"center",gap:4}}>
        {current.id} <span style={{fontSize:8,opacity:0.6}}>▼</span>
      </button>
      {open && (
        <div style={{position:"absolute",top:"100%",left:0,marginTop:4,
                     background:"#fff",border:"1px solid var(--grey-200)",borderRadius:6,
                     boxShadow:"0 4px 12px rgba(0,0,0,0.08)",zIndex:10,minWidth:80}}>
          {options.map(o => (
            <button key={o.id} onClick={()=>{onChange(o.id);setOpen(false);}}
              className={"adm-tag " + o.tone}
              style={{display:"block",width:"100%",border:0,background:"transparent",
                      padding:"6px 10px",cursor:"pointer",borderRadius:0,textAlign:"left"}}>
              {o.id}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

function App() {
  // v3.16: DAL에서 실시간 fetch (mock 비어있어도 안전)
  const [quotes, setQuotes] = useState(QL_INITIAL);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;
    async function load() {
      try {
        if (window.DAL?.listQuotes) {
          const data = await window.DAL.listQuotes();
          if (!cancelled && Array.isArray(data) && data.length > 0) {
            // Supabase 스키마 → 화면 형식 매핑
            setQuotes(data.map(d => ({
              no: d.quote_no || d.id,
              date: (d.issued_at || d.created_at || "").slice(0, 10),
              validUntil: d.valid_until,
              customer: d.customer_name,
              phone: d.customer_phone,
              bike: d.customer_bike,
              total: d.grand_total || 0,
              items: 0, parts: 0, labor: 0,
              status: d.status === "approved" ? "승인" : d.status === "expired" ? "만료" : d.status === "draft" ? "초안" : "대기",
              statusTone: d.status === "approved" ? "green" : d.status === "expired" ? "red" : "amber",
              issuedBy: d.issued_by_email || "—",
              note: d.customer_memo || "",
            })));
          }
        }
      } catch (e) {
        console.warn("[quotes-list] DAL fail:", e);
      } finally {
        if (!cancelled) setLoading(false);
      }
    }
    load();
    return () => { cancelled = true; };
  }, []);

  const QL = quotes;

  const [q, setQ] = useState("");
  const [status, setStatus] = useState("all");
  const [issuer, setIssuer] = useState("all");
  // v3.13 Q4: "내 견적만" 필터 (localStorage 영속, 기본 false)
  const [mineOnly, setMineOnly] = useState(() => {
    try { return localStorage.getItem("sejong-quote-filter") === "mine"; } catch { return false; }
  });
  React.useEffect(() => {
    try { localStorage.setItem("sejong-quote-filter", mineOnly ? "mine" : "all"); } catch {}
  }, [mineOnly]);
  const myName = window.AUTH?.user?.email?.split("@")[0] || window.AUTH?.user?.name || "";

  const [sortBy, setSortBy] = useState({ key: "date", dir: "desc" });
  // v3.11 A1: 인라인 상태 변경 후 로컬 상태 (Phase B에서 DAL 통합)
  const [statusOverride, setStatusOverride] = useState({});
  const setRowStatus = (no, st) => setStatusOverride(prev => ({ ...prev, [no]: st }));

  const issuers = useMemo(() => {
    const set = new Set(QL.map(x => x.issuedBy));
    return ["all", ...Array.from(set)];
  }, []);

  // 본인 견적 카운트 (mock: issuedBy === myName 매칭, 실 운영: created_by === user.id)
  const mineCount = useMemo(() => QL.filter(x =>
    (x.issuedBy || "").includes(myName) || x.issuedBy === myName
  ).length, [myName]);

  const filtered = useMemo(() => {
    const qs = q.trim().toLowerCase();
    let r = QL.filter(x => {
      if (status !== "all" && x.status !== status) return false;
      if (issuer !== "all" && x.issuedBy !== issuer) return false;
      if (mineOnly && !((x.issuedBy || "").includes(myName) || x.issuedBy === myName)) return false;
      if (qs && !(
        x.customer.toLowerCase().includes(qs) ||
        x.no.toLowerCase().includes(qs) ||
        x.bike.toLowerCase().includes(qs) ||
        (x.phone || "").includes(qs)
      )) return false;
      return true;
    });
    const dir = sortBy.dir === "asc" ? 1 : -1;
    r = [...r].sort((a, b) => {
      const av = a[sortBy.key], bv = b[sortBy.key];
      if (typeof av === "number") return (av - bv) * dir;
      return String(av).localeCompare(String(bv), "ko") * dir;
    });
    return r;
  }, [q, status, issuer, sortBy]);

  const toggleSort = (key) => {
    setSortBy(s => s.key === key ? { key, dir: s.dir === "asc" ? "desc" : "asc" } : { key, dir: "desc" });
  };

  return (
    <div className="inv-app">
      <Header total={QL.length} />
      <PageNav />
      <main className="inv-main">
        <div className="cat-inner">
          <div className="inv-page-head">
            <div>
              <h1 className="inv-page-h">견적서 목록</h1>
              <p className="inv-page-sub" style={{marginTop:10}}>
                발행한 모든 견적서를 한 화면에서. 상태별 필터링과 검색으로 빠르게 찾아보세요.
              </p>
            </div>
            <a className="cat-print-btn" href="서비스 견적서.html" style={{textDecoration:"none"}}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
              새 견적서 발행
            </a>
          </div>

          <KpiStrip list={filtered} />

          <div className="inv-toolbar">
            <div className="inv-toolbar-row">
              <div className="inv-toolbar-search">
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{color:"var(--fg-tertiary)"}}><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
                <input
                  placeholder="고객명 · 견적번호 · 차종 · 연락처로 검색"
                  value={q} onChange={(e)=>setQ(e.target.value)}
                />
              </div>
              {/* v3.13 Q4: 내 견적만 토글 */}
              <button
                onClick={()=>setMineOnly(v=>!v)}
                style={{
                  padding:"8px 14px", borderRadius:8, border:"1px solid "+(mineOnly?"var(--red-500,#E31E26)":"var(--grey-300,#D1D6DB)"),
                  background: mineOnly?"var(--red-50,#FFE5E6)":"#fff",
                  color: mineOnly?"var(--red-700,#9A0E14)":"var(--grey-700,#4E5968)",
                  fontSize:13, fontWeight: mineOnly?700:500, cursor:"pointer", whiteSpace:"nowrap",
                }}
                title="본인이 발행한 견적만 보기">
                {mineOnly ? "✓ 내 견적만" : "내 견적만"} <small style={{opacity:0.7,marginLeft:4}}>({mineCount})</small>
              </button>
              <button className="inv-tbl-action" onClick={() => { setQ(""); setStatus("all"); setIssuer("all"); setMineOnly(false); }}>
                필터 초기화
              </button>
            </div>
            <div className="inv-toolbar-row">
              <span className="inv-toolbar-label">상태</span>
              {STATUS_OPTIONS.map(s => (
                <button key={s.id} className={"inv-chip " + (status === s.id ? "on":"")} onClick={()=>setStatus(s.id)}>
                  {s.label}
                </button>
              ))}
              <div className="inv-divider" />
              <span className="inv-toolbar-label">발행자</span>
              {issuers.map(i => (
                <button key={i} className={"inv-chip " + (issuer === i ? "on":"")} onClick={()=>setIssuer(i)}>
                  {i === "all" ? "전체" : i}
                </button>
              ))}
            </div>
          </div>

          <div className="inv-tbl-wrap">
            <div className="inv-tbl-head">
              <div className="inv-tbl-h">견적서 {filtered.length}건 <small style={{marginLeft:8,fontWeight:500,color:"var(--fg-tertiary)",fontSize:11,letterSpacing:0,textTransform:"none"}}>합계 {fmtKRW(filtered.reduce((a,b)=>a+b.total,0))}</small></div>
            </div>
            <table className="inv-tbl">
              <thead>
                <tr>
                  <th style={{width:140}} className={sortBy.key === "no" ? "sorted":""} onClick={()=>toggleSort("no")}>견적번호 {sortBy.key === "no" ? (sortBy.dir === "asc" ? "▲":"▼") : "↕"}</th>
                  <th style={{width:110}} className={sortBy.key === "date" ? "sorted":""} onClick={()=>toggleSort("date")}>발행일 {sortBy.key === "date" ? (sortBy.dir === "asc" ? "▲":"▼") : "↕"}</th>
                  <th>고객 · 차량</th>
                  <th style={{width:120}}>구성</th>
                  <th style={{width:90}}>상태</th>
                  <th style={{width:80}}>발행자</th>
                  <th style={{width:110}}>유효기간</th>
                  <th className="num" style={{width:140}} onClick={()=>toggleSort("total")}>금액 {sortBy.key === "total" ? (sortBy.dir === "asc" ? "▲":"▼") : "↕"}</th>
                  <th className="center" style={{width:120}}>액션</th>
                </tr>
              </thead>
              <tbody>
                {filtered.map(qq => {
                  const isExpired = qq.status === "만료";
                  return (
                    <tr key={qq.no} className={isExpired ? "row-out" : ""}>
                      <td className="mono">{qq.no}</td>
                      <td style={{color:"var(--fg-tertiary)", fontSize:13}}>{qq.date.slice(5)}</td>
                      <td>
                        <div>
                          <b style={{font:"700 14px/1.2 var(--font-sans)", display:"block"}}>{qq.customer}</b>
                          <small style={{font:"500 12px/1.4 var(--font-sans)", color:"var(--fg-tertiary)", display:"block", marginTop:3}}>
                            {qq.bike} · {qq.phone}
                          </small>
                          {qq.note && <small style={{font:"400 11px/1.4 var(--font-sans)", color:"var(--fg-quaternary)", display:"block", marginTop:3, fontStyle:"italic"}}>"{qq.note}"</small>}
                        </div>
                      </td>
                      <td>
                        <div style={{display:"flex", gap:6, flexWrap:"wrap"}}>
                          {qq.parts > 0 && <span className="ql-comp part">파트 {qq.parts}</span>}
                          {qq.labor > 0 && <span className="ql-comp labor">공임 {qq.labor}</span>}
                        </div>
                      </td>
                      <td>
                        {/* A1: 인라인 상태 변경 (대기일 때만 - 상태별 정책) */}
                        <StatusDropdown
                          value={statusOverride[qq.no] || qq.status}
                          onChange={(s) => setRowStatus(qq.no, s)}
                        />
                      </td>
                      <td style={{fontSize:13, color:"var(--fg-secondary)"}}>{qq.issuedBy}</td>
                      <td style={{fontSize:12, color: isExpired ? "var(--red-500)" : "var(--fg-tertiary)"}}>
                        {qq.validUntil.slice(5)}
                        {/* A4: 응답 대기 시간 (대기/발송 상태일 때만) */}
                        {(qq.status === "대기" || qq.status === "발송") && (() => {
                          const h = waitingHours(qq.date);
                          if (h <= 0) return null;
                          const tone = h >= 24 ? "var(--red-500)" : h >= 12 ? "#DD7D02" : "var(--grey-500)";
                          return (
                            <div style={{fontSize:11,color:tone,marginTop:2,fontWeight:600}}>
                              {h >= 24 ? "🔴" : h >= 12 ? "🟡" : "⚪"} {h}시간 대기
                            </div>
                          );
                        })()}
                      </td>
                      <td className="num"><b style={{font:"800 15px/1 var(--font-sans)", fontFeatureSettings:'"tnum" 1'}}>{fmtKRW(qq.total)}</b></td>
                      <td className="center">
                        <div style={{display:"flex", gap:4, justifyContent:"center"}}>
                          <a href="서비스 견적서.html" className="ql-btn" title="열기">
                            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
                          </a>
                          <button className="ql-btn" title="복제">
                            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
                          </button>
                          <button className="ql-btn danger" title="삭제">
                            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg>
                          </button>
                        </div>
                      </td>
                    </tr>
                  );
                })}
                {filtered.length === 0 && (
                  <tr><td colSpan={9}>
                    <div style={{padding:"60px 24px",textAlign:"center",
                                 background:"var(--grey-50,#F9FAFB)",borderRadius:12,margin:8}}>
                      <div style={{fontSize:42,marginBottom:10}}>🧾</div>
                      <h3 style={{margin:"0 0 6px",font:"700 18px/1.3 var(--font-sans)"}}>
                        {loading ? "불러오는 중..." : QL.length === 0 ? "아직 견적이 없습니다" : "조건에 맞는 견적이 없어요"}
                      </h3>
                      <p style={{margin:"0 0 16px",color:"var(--grey-600)",fontSize:13}}>
                        {loading ? "" : QL.length === 0 ? "첫 견적을 발행하면 이곳에 표시됩니다." : "검색어/필터를 변경하거나 새 견적을 발행해보세요."}
                      </p>
                      {!loading && (
                        <a href="서비스 견적서.html" className="cat-btn cat-btn-primary"
                           style={{display:"inline-block",padding:"8px 20px",textDecoration:"none"}}>
                          + 새 견적서 발행
                        </a>
                      )}
                    </div>
                  </td></tr>
                )}
              </tbody>
            </table>
          </div>
        </div>
      </main>
    </div>
  );
}

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