/* global React */
// QA Runner — shared icons & mock data

const Icon = ({ name, size = 14, stroke = 1.6, style }) => {
  const props = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: stroke, strokeLinecap: "round", strokeLinejoin: "round", style };
  const paths = {
    chevronDown: <polyline points="6 9 12 15 18 9" />,
    chevronRight: <polyline points="9 6 15 12 9 18" />,
    chevronLeft: <polyline points="15 6 9 12 15 18" />,
    plus: <><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></>,
    play: <polygon points="5 3 19 12 5 21 5 3" fill="currentColor" stroke="none" />,
    playOutline: <polygon points="5 3 19 12 5 21 5 3" />,
    pause: <><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></>,
    stop: <rect x="5" y="5" width="14" height="14" rx="2" fill="currentColor" stroke="none" />,
    sparkles: <><path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.6 5.6l2.8 2.8M15.6 15.6l2.8 2.8M5.6 18.4l2.8-2.8M15.6 8.4l2.8-2.8"/></>,
    folder: <path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z"/>,
    file: <><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="14 3 14 9 20 9"/></>,
    code: <><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></>,
    terminal: <><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></>,
    settings: <><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h0a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51h0a1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v0a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></>,
    search: <><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></>,
    check: <polyline points="20 6 9 17 4 12"/>,
    x: <><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></>,
    history: <><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 15 14"/></>,
    grid: <><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></>,
    list: <><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></>,
    link: <><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></>,
    book: <><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></>,
    box: <><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></>,
    server: <><rect x="2" y="3" width="20" height="8" rx="2"/><rect x="2" y="13" width="20" height="8" rx="2"/><line x1="6" y1="7" x2="6.01" y2="7"/><line x1="6" y1="17" x2="6.01" y2="17"/></>,
    refresh: <><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></>,
    copy: <><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"/></>,
    download: <><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></>,
    arrow: <><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></>,
    moreH: <><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></>,
    eye: <><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></>,
    edit: <><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></>,
    trash: <><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></>,
    send: <><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></>,
    lock: <><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></>,
    cpu: <><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/><line x1="9" y1="2" x2="9" y2="4"/><line x1="15" y1="2" x2="15" y2="4"/><line x1="9" y1="20" x2="9" y2="22"/><line x1="15" y1="20" x2="15" y2="22"/><line x1="20" y1="9" x2="22" y2="9"/><line x1="20" y1="14" x2="22" y2="14"/><line x1="2" y1="9" x2="4" y2="9"/><line x1="2" y1="14" x2="4" y2="14"/></>,
    bolt: <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" fill="currentColor" stroke="none" />,
    filter: <polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/>,
    layers: <><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></>,
    branch: <><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></>,
    flask: <><path d="M9 2v6L4 18a2 2 0 0 0 1.7 3h12.6A2 2 0 0 0 20 18l-5-10V2"/><line x1="9" y1="2" x2="15" y2="2"/></>,
    zap: <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>,
  };
  return <svg {...props}>{paths[name]}</svg>;
};

// ─── Mock data ───────────────────────────────────────────────────────
const TREE = [
  {
    id: "gift", name: "Gift System", count: 24, expanded: true, suites: [
      { id: "sell", name: "Sell Gift", count: 8, expanded: true, cases: [
        { id: "TC-001", name: "User sells single gift, balance updates", method: "POST", path: "/gifts/sell", status: "pass", lastRun: "2m ago" },
        { id: "TC-002", name: "Sell with insufficient inventory returns 409", method: "POST", path: "/gifts/sell", status: "pass", lastRun: "2m ago" },
        { id: "TC-003", name: "Sell unauthenticated returns 401", method: "POST", path: "/gifts/sell", status: "fail", lastRun: "2m ago" },
        { id: "TC-004", name: "Sell with bundled discount applies coupon", method: "POST", path: "/gifts/sell", status: "running", lastRun: "now", active: true },
        { id: "TC-005", name: "Sell idempotency key prevents double charge", method: "POST", path: "/gifts/sell", status: "pass", lastRun: "5m ago" },
        { id: "TC-006", name: "Bulk sell processes 50 gifts atomically", method: "POST", path: "/gifts/sell/bulk", status: "idle", lastRun: "1h ago" },
        { id: "TC-007", name: "Refund flow reverses balance + inventory", method: "POST", path: "/gifts/refund", status: "draft", lastRun: "—" },
        { id: "TC-008", name: "Concurrent sells preserve inventory", method: "POST", path: "/gifts/sell", status: "pass", lastRun: "5m ago" },
      ]},
      { id: "inv", name: "Inventory", count: 6, expanded: false, cases: [] },
      { id: "promo", name: "Promotions", count: 5, expanded: false, cases: [] },
      { id: "ship", name: "Shipping", count: 5, expanded: false, cases: [] },
    ]
  },
  {
    id: "wallet", name: "Wallet", count: 12, expanded: false, suites: []
  },
  {
    id: "auth", name: "Authentication", count: 9, expanded: false, suites: []
  },
  {
    id: "search", name: "Search & Catalog", count: 7, expanded: false, suites: []
  },
];

const APIS = [
  { group: "Gift", method: "POST", path: "/gifts/sell", name: "Sell gift", desc: "Process a gift sale, debit wallet, decrement inventory." },
  { group: "Gift", method: "POST", path: "/gifts/sell/bulk", name: "Bulk sell" },
  { group: "Gift", method: "POST", path: "/gifts/refund", name: "Refund gift" },
  { group: "Gift", method: "GET",  path: "/gifts/{id}", name: "Get gift" },
  { group: "Gift", method: "GET",  path: "/gifts/inventory", name: "Inventory" },
  { group: "Wallet", method: "GET",  path: "/wallet/balance", name: "Get balance" },
  { group: "Wallet", method: "POST", path: "/wallet/topup", name: "Top up balance" },
  { group: "Wallet", method: "POST", path: "/wallet/transfer", name: "Transfer funds" },
  { group: "Auth",   method: "POST", path: "/auth/login", name: "Login" },
  { group: "Auth",   method: "POST", path: "/auth/refresh", name: "Refresh token" },
  { group: "Auth",   method: "DELETE", path: "/auth/session", name: "Logout" },
  { group: "Promo",  method: "GET",  path: "/promo/coupons", name: "List coupons" },
  { group: "Promo",  method: "POST", path: "/promo/apply", name: "Apply coupon" },
];

const FIXTURES = [
  { id: "ensure_balance", desc: "Topup if balance < threshold", params: "min_amount" },
  { id: "ensure_gift_stock", desc: "Seed if inventory < qty", params: "gift_id, qty" },
  { id: "create_test_user", desc: "Create temp user, auto-cleanup", params: "role?" },
  { id: "reset_wallet", desc: "Set balance to 0 for edge cases", params: "user_id?" },
  { id: "seed_gift_inventory", desc: "Add qty gifts to inventory", params: "gift_id, qty" },
];

const ENVS = [
  { id: "local", name: "local", color: "#6c6c78", base: "http://localhost:8000", auth: "static", active: false },
  { id: "stg", name: "staging", color: "oklch(0.78 0.13 230)", base: "https://api-stg.acme.dev", auth: "dynamic", active: true },
  { id: "prd", name: "production", color: "oklch(0.68 0.20 22)", base: "https://api.acme.dev", auth: "dynamic", active: false },
];

const RUN_HISTORY = [
  { id: "r-9821", tc: "TC-001", env: "staging", verdict: "pass", status: 200, ms: 184, when: "2m ago", by: "human:tinh" },
  { id: "r-9820", tc: "TC-002", env: "staging", verdict: "pass", status: 409, ms: 122, when: "2m ago", by: "human:tinh" },
  { id: "r-9819", tc: "TC-003", env: "staging", verdict: "fail", status: 200, ms: 156, when: "2m ago", by: "human:tinh", note: "Expected 401, got 200" },
  { id: "r-9818", tc: "TC-004", env: "staging", verdict: "pass", status: 200, ms: 312, when: "5m ago", by: "agent:claude-sonnet" },
  { id: "r-9817", tc: "TC-005", env: "staging", verdict: "pass", status: 200, ms: 201, when: "5m ago", by: "agent:claude-sonnet" },
  { id: "r-9816", tc: "TC-008", env: "staging", verdict: "pass", status: 200, ms: 1108, when: "5m ago", by: "agent:claude-sonnet" },
  { id: "r-9815", tc: "TC-001", env: "local", verdict: "pass", status: 200, ms: 92, when: "1h ago", by: "human:tinh" },
  { id: "r-9814", tc: "TC-007", env: "local", verdict: "error", status: 0, ms: 8, when: "1h ago", by: "human:tinh", note: "ConnectionError: refused" },
  { id: "r-9813", tc: "TC-002", env: "local", verdict: "pass", status: 409, ms: 78, when: "1h ago", by: "human:tinh" },
  { id: "r-9812", tc: "TC-006", env: "staging", verdict: "fail", status: 500, ms: 4012, when: "3h ago", by: "agent:gh-actions", note: "Inventory not atomic — race condition" },
];

Object.assign(window, { Icon, TREE, APIS, FIXTURES, ENVS, RUN_HISTORY });
