// view-pos.jsx — ③ POS連携状況画面（査定 → 連携 → 販促を繋ぐダッシュボード）
const { useState } = React;

function fmtPOS(n) { return n.toLocaleString("ja-JP"); }

// ===== data =====
// stock: POS→当社 参照 / 日次同期で取得
const ROWS = [
  { id: "A-2451", card: "蒼穹の終焉竜",    rarity: "SR",  price: 3200,  stock: 1,  status: "ok",   retries: 0,    time: "14:32:08", elapsed: "97ms",  to: "POS-A" },
  { id: "A-2450", card: "影翼の魔導師",    rarity: "R",   price: 480,   stock: 4,  status: "ok",   retries: 0,    time: "14:30:11", elapsed: "112ms", to: "POS-A" },
  { id: "A-2449", card: "雷光のドラゴン",  rarity: "UR",  price: 18500, stock: 0,  status: "warn", retries: "2/5",time: "14:28:42", elapsed: "—",     to: "POS-A" },
  { id: "A-2448", card: "守護の白翼天使",  rarity: "N",   price: 80,    stock: 12, status: "ok",   retries: 0,    time: "14:24:03", elapsed: "88ms",  to: "POS-A" },
  { id: "A-2447", card: "闇夜の刺客",      rarity: "SR",  price: 4200,  stock: 1,  status: "err",  retries: "5/5",time: "14:19:55", elapsed: "—",     to: "POS-A" },
  { id: "A-2446", card: "紅蓮の戦士王",    rarity: "SR",  price: 2800,  stock: 2,  status: "ok",   retries: 1,    time: "14:18:32", elapsed: "245ms", to: "POS-A" },
  { id: "A-2445", card: "森林の精霊女王",  rarity: "R",   price: 620,   stock: 3,  status: "ok",   retries: 0,    time: "14:15:18", elapsed: "104ms", to: "POS-A" },
  { id: "A-2444", card: "氷晶の戦姫",      rarity: "SEC", price: 28000, stock: 0,  status: "ok",   retries: 0,    time: "14:12:01", elapsed: "133ms", to: "POS-A" },
];

const KPIS = [
  { label: "本日の送信件数",     value: "187", unit: "件", trend: "+12 vs 昨日",              tone: "up"   },
  { label: "失敗（要再送）",     value: "1",   unit: "件", trend: "A-2447 闇夜の刺客",        tone: "down" },
];

// 24h queue depth — POS-A outage spike 14:00-15:00, drained by 16:00
const QUEUE = [0,0,0,0,0, 0,0,1,1,2, 1,2,3,2,12, 5,1,0,1,0, 0,0,0,0];

const DETAIL_BY_STATUS = {
  ok: {
    head: "POSに反映済み",
    sub:  "Square 商品マスタに登録。プライスタグ印刷キュー #4821 に積みました。",
    icon: "✓", chip: "success",
    log: [
      ["INFO","ok",  "price.confirmed event received"],
      ["INFO","ok",  "transform → POS payload v2.1 (square-adapter)"],
      ["INFO","ok",  "POST /v1/catalog/object/upsert 200 OK"],
      ["INFO","ok",  "tag-printer queue +1 (queue_len=4)"],
    ],
  },
  warn: {
    head: "リトライ中（2 / 5）",
    sub:  "Square API がタイムアウト。3秒間隔で自動リトライ。価格データはキューに保持中。",
    icon: "↻", chip: "warn",
    log: [
      ["INFO","ok",  "price.confirmed event received"],
      ["INFO","ok",  "POST dispatched"],
      ["WARN","warn","timeout after 5000ms — retry 1/5 scheduled"],
      ["WARN","warn","retry 1/5 → timeout — backoff 3000ms"],
      ["WARN","warn","retry 2/5 in-flight (POS-A latency 3.2s)"],
    ],
  },
  err: {
    head: "送信失敗 — 手動再送が必要",
    sub:  "5回のリトライ後も応答なし。キューに保持中。POS疎通を確認のうえ再送ボタンを押してください。",
    icon: "!", chip: "danger",
    log: [
      ["INFO","ok",  "price.confirmed event received"],
      ["INFO","ok",  "POST dispatched"],
      ["WARN","warn","retry 3/5 failed — HTTP 503"],
      ["WARN","warn","retry 4/5 failed — HTTP 503"],
      ["ERR ","err", "retry 5/5 failed → dead-letter queue"],
      ["ERR ","err", "user-action required"],
    ],
  },
};

// ===== components =====
function StatusBadge({ s }) {
  const label = s === "ok" ? "成功" : s === "warn" ? "送信中" : "失敗";
  return <span className={`status-led ${s}`}><span className="led" />{label}</span>;
}

function KPICard({ k }) {
  const isHead = k.tone === "headline";
  return (
    <div className={`kpi-card ${k.tone === "down" ? "danger" : ""} ${isHead ? "headline" : ""}`}>
      <div className="kpi-label">{k.label}{isHead && <span className="kpi-badge">主要指標</span>}</div>
      <div className="kpi-value">
        <span className="num">{k.value}</span>
        <span className="kpi-unit">{k.unit}</span>
      </div>
      <div className={`kpi-trend ${k.tone}`}>
        {isHead ? "↗ " : k.tone === "up" ? "▲ " : k.tone === "down" ? "● " : "· "}
        {k.trend}
      </div>
    </div>
  );
}

function StockBadge({ n }) {
  if (n === 0)      return <span className="stock-badge zero">在庫 0</span>;
  if (n === 1)      return <span className="stock-badge low">在庫 1</span>;
  return <span className="stock-badge ok">在庫 {n}</span>;
}

function SyncBar() {
  return (
    <div className="sync-bar">
      <div className="sync-row write">
        <span className="sync-dir">→</span>
        <span className="sync-label">価格データ <b>書き込み</b></span>
        <span className="sync-meta">当社 → POS-A</span>
        <span className="chip success">リアルタイム</span>
      </div>
      <div className="sync-divider" />
      <div className="sync-row read">
        <span className="sync-dir">←</span>
        <span className="sync-label">在庫データ <b>参照</b></span>
        <span className="sync-meta">POS-A → 当社</span>
        <span className="chip navy">日次バッチ · 最終同期 本日 06:00</span>
      </div>
    </div>
  );
}

function QueueChart() {
  const W = 800, H = 150;
  const padL = 36, padR = 16, padT = 14, padB = 26;
  const max = 14;
  const slotW = (W - padL - padR) / QUEUE.length;
  const barW = slotW - 4;
  const xAt = (i) => padL + i * slotW;
  const yAt = (v) => padT + (max - v) * (H - padT - padB) / max;

  return (
    <div className="card">
      <div className="card-head">
        <span className="h">キュー滞留状況（本日 0:00〜24:00）</span>
        <span className="chip danger">14:02 POS-A 一時停止 → +12件スパイク → 14:21 復旧で自動排出</span>
      </div>
      <div className="card-pad" style={{ paddingTop: 10 }}>
        <svg viewBox={`0 0 ${W} ${H}`} width="100%" preserveAspectRatio="xMidYMid meet" style={{display: "block"}}>
          {/* gridlines */}
          {[0,5,10,14].map(v => (
            <g key={v}>
              <line x1={padL} y1={yAt(v)} x2={W-padR} y2={yAt(v)} stroke="#e9e6d8" strokeWidth="1" />
              <text x={padL-6} y={yAt(v)+3} fontSize="9" textAnchor="end" fill="#9aa0aa" fontFamily="JetBrains Mono">{v}</text>
            </g>
          ))}
          {/* bars */}
          {QUEUE.map((v, i) => {
            const isSpike = v >= 8;
            return (
              <rect
                key={i}
                x={xAt(i) + 2}
                y={yAt(v)}
                width={barW}
                height={H - padB - yAt(v)}
                fill={isSpike ? "var(--danger)" : "#0f3a5f"}
                opacity={v === 0 ? 0.12 : 0.92}
                rx="1"
              />
            );
          })}
          {/* x labels */}
          {[0,3,6,9,12,15,18,21,23].map(i => (
            <text key={i} x={xAt(i)+barW/2} y={H-8} fontSize="9" textAnchor="middle" fill="#9aa0aa" fontFamily="JetBrains Mono">
              {i.toString().padStart(2,"0")}:00
            </text>
          ))}
          {/* annotation */}
          <g>
            <line x1={xAt(14)+barW/2} y1={yAt(12)-4} x2={xAt(14)+barW/2+58} y2={yAt(12)-22} stroke="var(--danger)" strokeWidth="1" />
            <circle cx={xAt(14)+barW/2} cy={yAt(12)-4} r="2" fill="var(--danger)" />
            <text x={xAt(14)+barW/2+62} y={yAt(12)-18} fontSize="10" fill="var(--danger)" fontFamily="JetBrains Mono" fontWeight="700">+12 件</text>
            <text x={xAt(14)+barW/2+62} y={yAt(12)-6} fontSize="9" fill="var(--danger)" fontFamily="JetBrains Mono">19分間 POS-A timeout</text>
          </g>
        </svg>
        <div className="chart-note">
          ✓ POSが一時停止しても <b>価格確定の業務は止まらない</b>。確定済みデータはキューに保持され、POS復旧後に自動で送信される。
        </div>
      </div>
    </div>
  );
}

function PosView() {
  const [selectedId, setSelectedId] = useState("A-2447"); // open on the failure
  const [toastDismissed, setToastDismissed] = useState(false);
  const [resentIds, setResentIds] = useState({});
  const selected = ROWS.find(r => r.id === selectedId) || ROWS[0];
  const detail = DETAIL_BY_STATUS[selected.status];

  const resend = (id) => {
    setResentIds(prev => ({...prev, [id]: true}));
    setTimeout(() => setToastDismissed(true), 200);
  };

  return (
    <div className="view" data-screen-label="03 POS">
      <div className="view-header">
        <div>
          <div className="crumb">③ 周辺 / POS連携状況画面（S-05）</div>
          <h1>POS連携ダッシュボード</h1>
          <div className="sub">
            価格確定 → POS送信を <b>査定ID単位</b> で運用可視化。POS側が止まってもキューに積まれ、業務は止まらない。
          </div>
        </div>
        <div className="header-side">
          <span className="chip">POS-A: Square</span>
          <span className="chip">webhook v2.1</span>
        </div>
      </div>

      {/* toast notification for failure */}
      {!toastDismissed && (
        <div className="pos-toast">
          <span className="toast-led" />
          <div className="toast-body">
            <div className="toast-title">送信失敗 — A-2447「闇夜の刺客」¥4,200</div>
            <div className="toast-sub">5回のリトライ後も応答なし。手動再送が必要です。</div>
          </div>
          <button className="btn btn-accent" onClick={() => { setSelectedId("A-2447"); resend("A-2447"); }}>↻ 再送する</button>
          <button className="btn-x" onClick={() => setToastDismissed(true)} aria-label="閉じる">×</button>
        </div>
      )}

      {/* L1 — bidirectional sync bar */}
      <SyncBar />

      {/* KPI strip */}
      <div className="kpi-row">
        {KPIS.map(k => <KPICard key={k.label} k={k} />)}
      </div>

      {/* Queue chart */}
      <QueueChart />

      {/* Main: table + detail */}
      <div className="pos-grid pos-grid-2">
        <div className="card">
          <div className="card-head">
            <span className="h">本日の査定 → POS送信ログ</span>
            <span className="row gap-sm">
              <span className="chip">{ROWS.length} 件</span>
              <span className="muted" style={{fontSize: 11}}>最終更新 14:32:08</span>
            </span>
          </div>
          <table className="market-table pos-table">
            <thead>
              <tr>
                <th>査定ID</th>
                <th>カード名</th>
                <th>レア</th>
                <th className="price-cell">価格</th>
                <th>在庫 ←POS</th>
                <th>ステータス</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {ROWS.map(r => {
                const resent = resentIds[r.id];
                const effStatus = resent ? "ok" : r.status;
                return (
                  <tr
                    key={r.id}
                    className={selectedId === r.id ? "is-selected" : ""}
                    onClick={() => setSelectedId(r.id)}>
                    <td className="num" style={{fontSize: 12, color: "var(--ink-3)"}}>{r.id}</td>
                    <td>
                      <span className="card-cell">
                        <b>{r.card}</b>
                        {r.stock === 0 && <span className="reorder-flag">強化買取候補</span>}
                      </span>
                    </td>
                    <td><span className="chip">{r.rarity}</span></td>
                    <td className="price-cell"><span className="num" style={{fontWeight: 700}}>¥{fmtPOS(r.price)}</span></td>
                    <td><StockBadge n={r.stock} /></td>
                    <td>
                      <StatusBadge s={effStatus} />
                      {(r.retries !== 0 && !resent) && <span className="retry-inline">· {r.retries}</span>}
                    </td>
                    <td onClick={(e) => e.stopPropagation()}>
                      {effStatus === "err" && (
                        <button className="btn btn-accent btn-xs" onClick={() => resend(r.id)}>↻ 再送</button>
                      )}
                      {effStatus === "warn" && (
                        <button className="btn btn-xs">× 中断</button>
                      )}
                      {effStatus === "ok" && resent && (
                        <span className="chip success" style={{fontSize: 10}}>✓ 再送成功</span>
                      )}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>

        {/* Selected row detail */}
        <div className="stack">
          <div className="card">
            <div className="card-head">
              <span className="h">送信詳細 / {selected.id}</span>
              <span className={`chip ${detail.chip}`}>
                {selected.status === "ok" ? "成功" : selected.status === "warn" ? "送信中" : "失敗"}
              </span>
            </div>
            <div className="card-pad">
              <div style={{display: "flex", gap: 14, alignItems: "flex-start", marginBottom: 14}}>
                <div className={`pos-icon-big ${detail.chip}`}>{detail.icon}</div>
                <div style={{flex: 1, minWidth: 0}}>
                  <div style={{fontSize: 14, fontWeight: 700}}>{detail.head}</div>
                  <div style={{fontSize: 11, color: "var(--ink-3)", marginTop: 4, lineHeight: 1.5}}>{detail.sub}</div>
                </div>
              </div>

              <dl className="kv-list compact" style={{marginBottom: 14}}>
                <dt>カード</dt><dd style={{fontFamily: "inherit", fontWeight: 600}}>{selected.card}</dd>
                <dt>レア / 価格</dt><dd>{selected.rarity} · ¥{fmtPOS(selected.price)}</dd>
                <dt>送信先</dt><dd>{selected.to}</dd>
                <dt>送信時刻</dt><dd>{selected.time}</dd>
                <dt>リトライ</dt><dd>{selected.retries === 0 ? "—" : selected.retries}</dd>
              </dl>

              <ul className="pos-log small">
                {detail.log.map((row, i) => (
                  <li key={i}>
                    <span className={`t-lvl ${row[1]}`}>[{row[0]}]</span>
                    <span className="t-msg">{row[2]}</span>
                  </li>
                ))}
              </ul>
            </div>

            {selected.status === "err" && !resentIds[selected.id] && (
              <div className="danger-action">
                <div className="da-title">⚠ アクションが必要です</div>
                <div className="da-text">
                  価格データはキューに保持されているので業務は継続できます。POSの疎通を確認後、ワンクリックで再送してください。
                </div>
                <div className="da-buttons">
                  <button className="btn btn-accent btn-block" onClick={() => resend(selected.id)}>↻ ワンクリック再送</button>
                  <button className="btn">📋 詳細ログ</button>
                </div>
              </div>
            )}

            {selected.status === "err" && resentIds[selected.id] && (
              <div className="success-action">
                <span className="check-big">✓</span>
                <div>
                  <div style={{fontWeight: 700, fontSize: 13}}>再送に成功しました</div>
                  <div style={{fontSize: 11, color: "var(--ink-3)", marginTop: 2}}>POS-A 商品マスタ反映 / 印刷キュー +1</div>
                </div>
              </div>
            )}
          </div>

          <div className="card">
            <div className="card-head"><span className="h">送信ペイロード</span><span className="chip">JSON</span></div>
            <pre className="pos-payload">
{`{
  `}<span className="k">"event"</span>{`: `}<span className="s">"price.confirmed"</span>{`,
  `}<span className="k">"sku"</span>{`: `}<span className="s">"BLU-EWD-001"</span>{`,
  `}<span className="k">"price_jpy"</span>{`: `}<span className="n">{selected.price}</span>{`,
  `}<span className="k">"rarity"</span>{`: `}<span className="s">"{selected.rarity}"</span>{`,
  `}<span className="k">"operator"</span>{`: `}<span className="s">"staff_021"</span>{`
}`}
            </pre>
          </div>
        </div>
      </div>
    </div>
  );
}

window.PosView = PosView;
