// integration.jsx — 数据接入监控
// 后端数据管理总览：所有车辆的 GB32960 / JT808+1078 对接情况、最后接收时间
// 完全未对接的车辆重点标记，便于发现新车未接入或数据停止上报。

const fmtRelative = (ts) => {
  if (!ts) return "—";
  const diff = Date.now() - ts;
  const m = Math.floor(diff / 60000);
  if (m < 1) return "刚刚";
  if (m < 60) return m + " 分钟前";
  const h = Math.floor(m / 60);
  if (h < 24) return h + " 小时前";
  const d = Math.floor(h / 24);
  return d + " 天前";
};

const fmtAbsolute = (ts) => {
  if (!ts) return "—";
  const d = new Date(ts);
  const pad = (n) => String(n).padStart(2, "0");
  return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
};

const fmtDate = (ts) => {
  if (!ts) return "—";
  const d = new Date(ts);
  const pad = (n) => String(n).padStart(2, "0");
  return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`;
};

// 24h 未上报阈值
const STALE_THRESHOLD = 24 * 60 * 60 * 1000;

// 派生有效状态：offline 且 last_seen > 24h → abnormal（异常）
const effectiveStatus = (rawStatus, lastSeen) => {
  if (rawStatus === "online" || rawStatus === "not_connected") return rawStatus;
  // offline
  if (lastSeen && Date.now() - lastSeen > STALE_THRESHOLD) return "abnormal";
  return "offline";
};

// 是否为"红色重点"状态（需要业务跟进）
const isRedState = (st) => st === "abnormal" || st === "not_connected";

// Status pill
const ConnPill = ({ status, protocol }) => {
  const map = {
    online:        { bg:"var(--accent-soft)", fg:"var(--accent)",  bd:"rgba(0,113,67,0.30)",  dot:"var(--accent)", l:"在线" },
    offline:       { bg:"var(--warn-soft)",   fg:"var(--warn)",    bd:"rgba(181,122,14,0.35)", dot:"var(--warn)",   l:"断流 <24h" },
    abnormal:      { bg:"var(--danger-soft)", fg:"var(--danger)",  bd:"rgba(179,48,40,0.40)",  dot:"var(--danger)", l:"异常 ≥24h" },
    not_connected: { bg:"var(--danger-soft)", fg:"var(--danger)",  bd:"rgba(179,48,40,0.40)",  dot:"var(--danger)", l:"未对接" },
  };
  const m = map[status] || map.not_connected;
  return (
    <span style={{
      display:"inline-flex", alignItems:"center", gap:5,
      height:21, padding:"0 8px",
      fontSize:11, fontWeight:500,
      borderRadius:4,
      background:m.bg, color:m.fg, border:"1px solid "+m.bd,
      whiteSpace:"nowrap",
    }}>
      <span style={{
        width:6, height:6, borderRadius:3, background:m.dot,
        boxShadow: status === "online" ? "0 0 4px " + m.dot : "none",
        animation: status === "online" ? "pulse 1.6s ease-in-out infinite" : "none",
      }}/>
      {protocol && <span style={{fontFamily:"var(--font-mono)", fontSize:9, opacity:.7, marginRight:2}}>{protocol}</span>}
      {m.l}
    </span>
  );
};

const KpiCard = ({ label, value, sub, tone, accent }) => {
  const toneMap = {
    ok:     { fg:"var(--accent)", bg:"var(--accent-soft)", bd:"rgba(0,113,67,0.20)" },
    warn:   { fg:"var(--warn)",   bg:"var(--warn-soft)",   bd:"rgba(181,122,14,0.25)" },
    danger: { fg:"var(--danger)", bg:"var(--danger-soft)", bd:"rgba(179,48,40,0.30)" },
    neutral:{ fg:"var(--fg-0)",   bg:"var(--bg-2)",        bd:"var(--border-1)" },
  };
  const t = toneMap[tone] || toneMap.neutral;
  return (
    <div style={{
      flex:1, minWidth:160,
      padding:"14px 16px",
      background:"var(--bg-1)",
      border:"1px solid var(--border-1)",
      borderRadius:8,
      position:"relative",
      overflow:"hidden",
    }}>
      {accent && <div style={{position:"absolute", top:0, left:0, bottom:0, width:3, background:t.fg}}/>}
      <div style={{fontSize:11, color:"var(--fg-3)", textTransform:"uppercase", letterSpacing:".1em", fontWeight:500}}>{label}</div>
      <div style={{display:"flex", alignItems:"baseline", gap:6, marginTop:6}}>
        <span style={{fontFamily:"var(--font-mono)", fontSize:24, fontWeight:600, color:t.fg, fontVariantNumeric:"tabular-nums"}}>{value}</span>
        {sub && <span style={{fontSize:11, color:"var(--fg-3)"}}>{sub}</span>}
      </div>
    </div>
  );
};

const ArtboardIntegration = () => {
  const allVehicles = (window.VEHICLES || []);
  const counts = (window.COUNTS || {});

  const [filterMode, setFilterMode] = React.useState("all"); // all | online | offline | not_connected | both_none
  const [search, setSearch] = React.useState("");
  const [sortBy, setSortBy] = React.useState("priority"); // priority | plate | gbTime | jtTime
  const [tick, setTick] = React.useState(0);

  // 实时刷新相对时间显示
  React.useEffect(() => {
    const id = setInterval(() => setTick((x) => x + 1), 30000);
    return () => clearInterval(id);
  }, []);

  // 派生重点标记 + 状态等级（用于排序）
  // tick 让 useMemo 在定时器触发时重算时间相关状态
  const enriched = React.useMemo(() => allVehicles.map(v => {
    const gbEff = effectiveStatus(v.gbStatus, v.gbLastSeen);
    const jtEff = effectiveStatus(v.jtStatus, v.jtLastSeen);
    // 重点标记：双通道都是红色状态（异常 或 未对接）
    const isCritical = isRedState(gbEff) && isRedState(jtEff);
    const hasOffline = gbEff === "offline" || jtEff === "offline";
    const hasAbnormal = gbEff === "abnormal" || jtEff === "abnormal";
    const hasNotConn = gbEff === "not_connected" || jtEff === "not_connected";
    const allOnline  = gbEff === "online" && jtEff === "online";
    let priority = 5;
    if (isCritical) priority = 0;
    else if (hasNotConn) priority = 1;
    else if (hasAbnormal) priority = 2;
    else if (hasOffline) priority = 3;
    else if (allOnline) priority = 4;
    return { ...v, gbEff, jtEff, isCritical, hasOffline, hasAbnormal, hasNotConn, allOnline, priority };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }), [allVehicles, tick]);

  const filtered = enriched.filter(v => {
    if (filterMode === "online" && !(v.gbEff === "online" || v.jtEff === "online")) return false;
    if (filterMode === "offline" && !v.hasOffline) return false;
    if (filterMode === "abnormal" && !(v.hasAbnormal || v.hasNotConn)) return false;
    if (filterMode === "both_none" && !v.isCritical) return false;
    if (search) {
      const q = search.toLowerCase();
      if (!v.plate.toLowerCase().includes(q) &&
          !v.vin.toLowerCase().includes(q) &&
          !v.brand.toLowerCase().includes(q) &&
          !v.model.toLowerCase().includes(q)) return false;
    }
    return true;
  });

  const sorted = [...filtered].sort((a, b) => {
    if (sortBy === "priority") return a.priority - b.priority;
    if (sortBy === "plate") return a.plate.localeCompare(b.plate);
    if (sortBy === "gbTime") return (b.gbLastSeen || 0) - (a.gbLastSeen || 0);
    if (sortBy === "jtTime") return (b.jtLastSeen || 0) - (a.jtLastSeen || 0);
    return 0;
  });

  // 派生计数（基于 effectiveStatus）
  const derivedCounts = React.useMemo(() => {
    const c = { gbOnline:0, gbOffline:0, gbAbnormal:0, gbNotConn:0, jtOnline:0, jtOffline:0, jtAbnormal:0, jtNotConn:0, anyOnline:0, hasOffline:0, hasAbnormalOrNC:0, bothRed:0 };
    enriched.forEach(v => {
      if (v.gbEff === "online") c.gbOnline++;
      else if (v.gbEff === "offline") c.gbOffline++;
      else if (v.gbEff === "abnormal") c.gbAbnormal++;
      else c.gbNotConn++;
      if (v.jtEff === "online") c.jtOnline++;
      else if (v.jtEff === "offline") c.jtOffline++;
      else if (v.jtEff === "abnormal") c.jtAbnormal++;
      else c.jtNotConn++;
      if (v.gbEff === "online" || v.jtEff === "online") c.anyOnline++;
      if (v.hasOffline) c.hasOffline++;
      if (v.hasAbnormal || v.hasNotConn) c.hasAbnormalOrNC++;
      if (v.isCritical) c.bothRed++;
    });
    return c;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [enriched, tick]);

  const filters = [
    { k: "all",       l: "全部",        c: enriched.length,            tone: "neutral" },
    { k: "online",    l: "任一在线",    c: derivedCounts.anyOnline,    tone: "ok" },
    { k: "offline",   l: "断流 <24h",   c: derivedCounts.hasOffline,   tone: "warn" },
    { k: "abnormal",  l: "异常 ≥24h",   c: derivedCounts.hasAbnormalOrNC, tone: "danger" },
    { k: "both_none", l: "完全未对接",  c: derivedCounts.bothRed,      tone: "danger" },
  ];

  return (
    <div className="app">
      <Sidebar active="integration"/>
      <div style={{flex:1, display:"flex", flexDirection:"column", minWidth:0, position:"relative", zIndex:1}}>
        <Topbar
          crumbs={["羚牛车辆数据中心", "数据接入", "监控总览"]}
          kpis={[
            { lbl:"总车辆", val: enriched.length },
            { lbl:"GB在线", val: derivedCounts.gbOnline },
            { lbl:"JT在线", val: derivedCounts.jtOnline },
            { lbl:"完全未对接", val: derivedCounts.bothRed, deltaUp:false, delta: derivedCounts.bothRed > 0 ? "需处理" : "—" },
          ]}
        />

        {/* 顶部 banner — 如果有完全未对接车辆，全屏告警条 */}
        {derivedCounts.bothRed > 0 && (
          <div style={{
            padding:"10px 18px",
            background:"linear-gradient(90deg, var(--danger-soft), transparent)",
            borderBottom:"1px solid rgba(179,48,40,0.25)",
            fontSize:12,
            display:"flex", alignItems:"center", gap:12, color:"var(--fg-1)",
          }}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--danger)" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
              <path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/>
              <line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>
            </svg>
            <span>检测到 <span className="strong" style={{color:"var(--danger)", fontFamily:"var(--font-mono)", fontWeight:600}}>{derivedCounts.bothRed}</span> 辆车 GB32960 与 JT808 双协议均处于"未对接 / 超 24h 未上报"状态，可能为新增/更换车机后未配置上行 — 请尽快在对应业务系统下工单核查。</span>
            <button className="btn" style={{marginLeft:"auto", height:24, padding:"0 10px", fontSize:11}} onClick={() => setFilterMode("both_none")}>
              查看全部 →
            </button>
          </div>
        )}

        {/* KPI 行 */}
        <div style={{display:"flex", gap:12, padding:"16px 18px 0"}}>
          <KpiCard label="总车辆"        value={enriched.length}                                          tone="neutral" accent/>
          <KpiCard label="GB32960 接入"  value={derivedCounts.gbOnline}  sub={`/ ${enriched.length}`}    tone="ok" accent/>
          <KpiCard label="GB 异常 ≥24h"  value={derivedCounts.gbAbnormal + derivedCounts.gbNotConn}      tone="danger" accent/>
          <KpiCard label="JT808/1078"    value={derivedCounts.jtOnline}  sub={`/ ${enriched.length}`}    tone="ok" accent/>
          <KpiCard label="JT 异常 ≥24h"  value={derivedCounts.jtAbnormal + derivedCounts.jtNotConn}      tone="danger" accent/>
          <KpiCard label="完全未对接"    value={derivedCounts.bothRed}   sub={derivedCounts.bothRed > 0 ? "重点处理" : "—"} tone="danger" accent/>
        </div>

        {/* 工具栏 */}
        <div style={{padding:"14px 18px 10px", display:"flex", alignItems:"center", gap:12, flexWrap:"wrap"}}>
          <div className="search" style={{maxWidth:280, marginLeft:0}}>
            <Icon name="search" size={13}/>
            <input placeholder="车牌 / VIN / 品牌 / 型号"
                   value={search}
                   onChange={e => setSearch(e.target.value)}/>
          </div>

          <div style={{display:"flex", gap:6, flexWrap:"wrap"}}>
            {filters.map(f => (
              <span key={f.k}
                    onClick={() => setFilterMode(f.k)}
                    className="chip"
                    style={{
                      cursor:"pointer", fontSize:11, height:26, padding:"0 10px",
                      background: filterMode === f.k
                        ? (f.tone === "danger" ? "var(--danger-soft)" : f.tone === "warn" ? "var(--warn-soft)" : f.tone === "ok" ? "var(--accent-soft)" : "var(--bg-3)")
                        : "var(--bg-2)",
                      color: filterMode === f.k
                        ? (f.tone === "danger" ? "var(--danger)" : f.tone === "warn" ? "var(--warn)" : f.tone === "ok" ? "var(--accent)" : "var(--fg-0)")
                        : "var(--fg-2)",
                      border: "1px solid " + (filterMode === f.k
                        ? (f.tone === "danger" ? "rgba(179,48,40,0.30)" : f.tone === "warn" ? "rgba(181,122,14,0.30)" : f.tone === "ok" ? "rgba(0,113,67,0.25)" : "var(--border-2)")
                        : "var(--border-1)"),
                      fontWeight: filterMode === f.k ? 500 : 400,
                    }}>
                {f.l}
                <span className="mono" style={{marginLeft:6, fontSize:10, opacity:.75}}>{f.c}</span>
              </span>
            ))}
          </div>

          <div style={{marginLeft:"auto", display:"flex", gap:8, alignItems:"center", fontSize:11, color:"var(--fg-3)"}}>
            <span>排序</span>
            <select value={sortBy} onChange={e => setSortBy(e.target.value)} style={{
              height:28, padding:"0 8px", fontSize:11, fontFamily:"inherit",
              background:"var(--bg-1)", border:"1px solid var(--border-1)", borderRadius:6,
              color:"var(--fg-1)", cursor:"pointer",
            }}>
              <option value="priority">优先级（未对接置顶）</option>
              <option value="plate">车牌升序</option>
              <option value="gbTime">GB32960 最新</option>
              <option value="jtTime">JT 最新</option>
            </select>
            <button className="btn" style={{height:28, padding:"0 10px", fontSize:11}}>
              <Icon name="download" size={12}/>
              导出 CSV
            </button>
          </div>
        </div>

        {/* 表格 */}
        <div className="scroll" style={{flex:1, padding:"0 18px 18px", minHeight:0, overflow:"auto"}}>
          <div style={{
            background:"var(--bg-1)",
            border:"1px solid var(--border-1)",
            borderRadius:8, overflow:"hidden",
          }}>
            <table className="tbl" style={{width:"100%"}}>
              <thead>
                <tr>
                  <th style={{width:24}}></th>
                  <th style={{width:120}}>车牌</th>
                  <th style={{width:200}}>VIN / 车架号</th>
                  <th>品牌 / 型号</th>
                  <th style={{width:130}}>GB32960</th>
                  <th style={{width:170}}>GB32960 最后接收</th>
                  <th style={{width:140}}>JT808 / 1078</th>
                  <th style={{width:170}}>JT 最后接收</th>
                  <th style={{width:120}}>接入时间</th>
                  <th style={{width:80}}></th>
                </tr>
              </thead>
              <tbody>
                {sorted.map(v => {
                  const flagged = v.isCritical;
                  return (
                    <tr key={v.id} style={{
                      background: flagged ? "rgba(179,48,40,0.05)" : "transparent",
                      cursor:"pointer",
                    }}>
                      <td style={{padding:"10px 6px 10px 14px", verticalAlign:"middle"}}>
                        {flagged ? (
                          <span title="完全未对接 — 重点处理" style={{
                            display:"inline-flex", alignItems:"center", justifyContent:"center",
                            width:20, height:20, borderRadius:10,
                            background:"var(--danger)", color:"#fff",
                          }}>
                            <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
                              <line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>
                              <path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/>
                            </svg>
                          </span>
                        ) : v.hasOffline ? (
                          <span title="存在断流通道" style={{display:"inline-block", width:6, height:6, borderRadius:3, background:"var(--warn)", boxShadow:"0 0 4px rgba(181,122,14,0.4)"}}/>
                        ) : null}
                      </td>
                      <td className="mono" style={{fontWeight:600, color: flagged ? "var(--danger)" : "var(--fg-0)"}}>
                        {v.plate}
                      </td>
                      <td className="mono" style={{color:"var(--fg-2)", fontSize:11}}>
                        {v.vin}
                      </td>
                      <td>
                        <div style={{display:"flex", flexDirection:"column", gap:2}}>
                          <span style={{fontWeight:500, color:"var(--fg-0)", fontSize:12}}>{v.brand}</span>
                          <span style={{color:"var(--fg-3)", fontSize:11}}>{v.model}</span>
                        </div>
                      </td>
                      <td>
                        <ConnPill status={v.gbEff} protocol="GB"/>
                      </td>
                      <td className="mono" style={{color: v.gbEff === "not_connected" ? "var(--fg-3)" : v.gbEff === "abnormal" ? "var(--danger)" : v.gbEff === "offline" ? "var(--warn)" : "var(--fg-1)"}}>
                        {v.gbLastSeen ? (
                          <div style={{display:"flex", flexDirection:"column", gap:1, fontSize:11}}>
                            <span>{fmtRelative(v.gbLastSeen)}</span>
                            <span style={{color:"var(--fg-3)", fontSize:10}}>{fmtAbsolute(v.gbLastSeen)}</span>
                          </div>
                        ) : <span style={{color:"var(--fg-3)"}}>—</span>}
                      </td>
                      <td>
                        <ConnPill status={v.jtEff} protocol="JT"/>
                      </td>
                      <td className="mono" style={{color: v.jtEff === "not_connected" ? "var(--fg-3)" : v.jtEff === "abnormal" ? "var(--danger)" : v.jtEff === "offline" ? "var(--warn)" : "var(--fg-1)"}}>
                        {v.jtLastSeen ? (
                          <div style={{display:"flex", flexDirection:"column", gap:1, fontSize:11}}>
                            <span>{fmtRelative(v.jtLastSeen)}</span>
                            <span style={{color:"var(--fg-3)", fontSize:10}}>{fmtAbsolute(v.jtLastSeen)}</span>
                          </div>
                        ) : <span style={{color:"var(--fg-3)"}}>—</span>}
                      </td>
                      <td className="mono" style={{color:"var(--fg-2)", fontSize:11}}>
                        {fmtDate(v.onboardAt)}
                      </td>
                      <td>
                        <button className="btn" style={{height:24, padding:"0 8px", fontSize:11}} onClick={() => location.hash = "#/detail"}>
                          查看
                        </button>
                      </td>
                    </tr>
                  );
                })}
                {sorted.length === 0 && (
                  <tr><td colSpan={10} style={{textAlign:"center", padding:40, color:"var(--fg-3)", fontSize:12}}>没有匹配的车辆</td></tr>
                )}
              </tbody>
            </table>
          </div>

          <div style={{padding:"10px 4px", display:"flex", justifyContent:"space-between", fontSize:11, color:"var(--fg-3)"}}>
            <span>共 <span className="mono strong" style={{color:"var(--fg-1)"}}>{sorted.length}</span> 辆车 · 数据每 30 秒刷新一次</span>
            <span>处理流程：发现未对接 → 在车联网平台下工单 → 配置 TBOX/JT 主机参数 → 回流验证</span>
          </div>
        </div>
      </div>
    </div>
  );
};

window.ArtboardIntegration = ArtboardIntegration;
