from __future__ import annotations

import argparse
import json
import re
import sys
import threading
import time
from pathlib import Path
from typing import Any

from common.credential_parser import clean_key_token, extract_ak_sk, extract_mark, is_hex_id
from common.runtime_paths import resource_path


CLOUD_CREDENTIAL_PAGE_URLS = {
    "huawei": "https://console.huaweicloud.com/iam5/?locale=zh-cn&region=cn-east-3#/credentials",
    "ctyun": "https://iam.ctyun.cn/myAccessKey",
    "volc": "https://console.volcengine.com/iam/keymanage",
}
CLOUD_CREDENTIAL_PAGE_NAMES = {
    "huawei": "华为云",
    "ctyun": "天翼云",
    "volc": "火山引擎",
}
CLOUD_CREDENTIAL_WINDOW_ICONS = {
    "huawei": "web_login_huawei.ico",
    "ctyun": "web_login_ctyun.ico",
    "volc": "web_login_volc.ico",
}
_WEB_LOGIN_CLIPBOARD_CACHE: dict[str, dict[str, str]] = {}
WEBVIEW2_MISSING_MESSAGE = "无法启动内嵌网页登录窗口，请确认本机已安装 Microsoft Edge WebView2 Runtime。"
WEBVIEW_IMPORT_MISSING_MESSAGE = "当前软件包未包含内嵌网页登录组件，请更新到包含 WebView2 登录组件的版本后再试。"
CTYUN_KEY_RE = re.compile(r"\b[a-fA-F0-9]{32}\b")
AK_LABEL_RE = re.compile(
    r"Access\s*Key\s*ID|AccessKey\s*ID|AccessKeyID|访问密钥\s*(?:AK|ID)|\bAK\b",
    re.IGNORECASE,
)
SK_LABEL_RE = re.compile(
    r"Security\s*Key|SecurityKey|Secret\s*Access\s*Key|SecretAccessKey|Secret\s*Key|SecretKey|"
    r"访问密钥\s*SK|密钥\s*SK|\bSK\b",
    re.IGNORECASE,
)
HUAWEI_SECRET_VALUE_RE = re.compile(r"^[A-Za-z0-9+/=_-]{24,128}$")
HUAWEI_MASKED_SECRET_RE = re.compile(r"(?:Security\s*Key|Secret\s*Key|SecretKey|密钥)[\s:：]*\*{4,}", re.IGNORECASE)
HUAWEI_PAGE_SCRIPT_TOKEN_RE = re.compile(
    r"DeleteXdm|XdmOperation|OperationRelation|(?:Create|Delete|Update|Query)[A-Z][A-Za-z]*(?:Operation|Relation)"
)


def _write_result(path: Path | None, data: dict[str, Any]) -> None:
    payload = json.dumps(data, ensure_ascii=False, separators=(",", ":"))
    if path is None:
        if hasattr(sys.stdout, "reconfigure"):
            sys.stdout.reconfigure(encoding="utf-8", errors="replace")
        print(payload, flush=True)
        return
    path.parent.mkdir(parents=True, exist_ok=True)
    temp_path = path.with_suffix(path.suffix + ".tmp")
    temp_path.write_text(payload, encoding="utf-8")
    temp_path.replace(path)


def _page_snapshot_script() -> str:
    return r"""
(() => {
  const textOf = (el) => String((el && (el.innerText || el.textContent)) || "").replace(/\s+/g, " ").trim();
  const attrTextOf = (el) => {
    if (!el) return "";
    const values = [
      el.getAttribute("title") || "",
      el.getAttribute("aria-label") || "",
      el.getAttribute("data-clipboard-text") || "",
      el.getAttribute("data-copy") || "",
      el.getAttribute("data-row-key") || "",
      el.value || "",
    ];
    for (const child of Array.from(el.querySelectorAll("[title],[aria-label],[data-clipboard-text],[data-copy],input,textarea")).slice(0, 32)) {
      values.push(child.getAttribute("title") || "");
      values.push(child.getAttribute("aria-label") || "");
      values.push(child.getAttribute("data-clipboard-text") || "");
      values.push(child.getAttribute("data-copy") || "");
      values.push(child.value || "");
    }
    return values.filter(Boolean).join(" ");
  };
  const keyMeta = /access\s*key|accesskey|secret|security\s*key|访问密钥|密钥|ak|sk/i;
  const rows = [];
  const seenRows = new Set();
  for (const row of Array.from(document.querySelectorAll("tr,[role='row'],.ant-table-row,.el-table__row,.arco-table-tr,.arco-table-row"))) {
    const text = textOf(row);
    const richText = [text, attrTextOf(row)].filter(Boolean).join(" ");
    if (!richText || seenRows.has(richText)) {
      continue;
    }
    seenRows.add(richText);
    const cells = Array.from(row.querySelectorAll("td,th,[role='cell'],.arco-table-td,.arco-table-cell,.ant-table-cell,.el-table__cell"))
      .map((cell) => [textOf(cell), attrTextOf(cell)].filter(Boolean).join(" "))
      .filter(Boolean);
    rows.push({text: richText, cells});
  }
  const fields = [];
  for (const el of Array.from(document.querySelectorAll("input, textarea"))) {
    const labelText = el.labels ? Array.from(el.labels).map((item) => item.innerText || item.textContent || "").join(" ") : "";
    const prevText = el.previousElementSibling ? (el.previousElementSibling.innerText || el.previousElementSibling.textContent || "") : "";
    const meta = [
      el.name || "",
      el.id || "",
      el.placeholder || "",
      el.getAttribute("aria-label") || "",
      el.getAttribute("title") || "",
      labelText,
      prevText,
    ].join(" ");
    const value = String(el.value || "").trim();
    if (value && keyMeta.test(meta)) {
      fields.push({meta, value});
    }
  }
  const pageClipboard = Array.isArray(window.__wawaCredentialCopiedTexts)
    ? window.__wawaCredentialCopiedTexts.slice(-8)
    : [];
  const text = [
    document.title || "",
    location.href || "",
    document.body ? (document.body.innerText || document.body.textContent || "") : "",
  ].join("\n").slice(-400000);
  return JSON.stringify({title: document.title || "", url: location.href || "", text, rows, fields, pageClipboard});
})()
"""


def _page_automation_script(vendor: str) -> str:
    vendor_json = json.dumps(vendor)
    return r"""
(() => {
  const vendor = __VENDOR__;
  const textOf = (el) => String((el && (el.innerText || el.textContent)) || "").replace(/\s+/g, " ").trim();
  const visible = (el) => {
    if (!el) return false;
    const style = getComputedStyle(el);
    if (style.display === "none" || style.visibility === "hidden" || Number(style.opacity || "1") === 0) return false;
    const box = el.getBoundingClientRect();
    return box.width > 0 && box.height > 0;
  };
  const nativeClickable = (el) => {
    if (!el) return false;
    const tag = String(el.tagName || "").toLowerCase();
    const cls = String(el.className || "");
    return tag === "button" || tag === "a" || el.getAttribute("role") === "button" || /\b(ant-btn|el-button|veui-button)\b|button|btn/i.test(cls);
  };
  const clickableOf = (el) => el && (el.closest("button,a,[role='button'],.ant-btn,.el-button,.veui-button") || (nativeClickable(el) ? el : null));
  const disabledState = (el) => {
    if (!el) return true;
    for (let current = el; current && current !== document.body; current = current.parentElement) {
      if (current.disabled || current.getAttribute("aria-disabled") === "true" || /\bdisabled\b/.test(String(current.className || ""))) return true;
    }
    return false;
  };
  const actionTargetOf = (el) => {
    if (!el) return null;
    const direct = clickableOf(el);
    if (direct) return direct;
    const tag = String(el.tagName || "").toLowerCase();
    let current = (tag === "svg" || tag === "path" || tag === "i" || tag === "use") ? el.parentElement : el;
    for (let depth = 0; current && current !== document.body && depth < 6; depth += 1, current = current.parentElement) {
      const cls = String(current.className || "");
      const role = String(current.getAttribute("role") || "");
      const style = getComputedStyle(current);
      const box = current.getBoundingClientRect();
      if (
        nativeClickable(current) ||
        role === "checkbox" ||
        current.hasAttribute("tabindex") ||
        style.cursor === "pointer" ||
        /button|btn|link|action|operate|operation|checkbox|icon|eye|visible/i.test(cls) ||
        (box.width <= 180 && box.height <= 80)
      ) {
        return current;
      }
    }
    return el;
  };
  const dispatchClick = (target, source = target) => {
    if (!target || !visible(target) || disabledState(target)) return false;
    try {
      target.scrollIntoView({block: "center", inline: "center"});
    } catch (_error) {
    }
    const box = (source || target).getBoundingClientRect();
    const x = Math.max(1, Math.min(window.innerWidth - 1, box.left + box.width / 2));
    const y = Math.max(1, Math.min(window.innerHeight - 1, box.top + box.height / 2));
    const pointed = document.elementFromPoint(x, y);
    const receiver = actionTargetOf(pointed) || actionTargetOf(target) || target;
    const options = {bubbles: true, cancelable: true, view: window, clientX: x, clientY: y};
    try {
      receiver.dispatchEvent(new PointerEvent("pointerdown", options));
      receiver.dispatchEvent(new PointerEvent("pointerup", options));
    } catch (_error) {
    }
    receiver.dispatchEvent(new MouseEvent("mouseover", options));
    receiver.dispatchEvent(new MouseEvent("mousedown", options));
    receiver.dispatchEvent(new MouseEvent("mouseup", options));
    receiver.dispatchEvent(new MouseEvent("click", options));
    try {
      receiver.click();
    } catch (_error) {
    }
    return true;
  };
  const dispatchClickNoScroll = (target, source = target) => {
    if (!target || !visible(target) || disabledState(target)) return false;
    const box = (source || target).getBoundingClientRect();
    const x = Math.max(1, Math.min(window.innerWidth - 1, box.left + box.width / 2));
    const y = Math.max(1, Math.min(window.innerHeight - 1, box.top + box.height / 2));
    const pointed = document.elementFromPoint(x, y);
    const receiver = actionTargetOf(pointed) || actionTargetOf(target) || target;
    const options = {bubbles: true, cancelable: true, view: window, clientX: x, clientY: y};
    try {
      receiver.dispatchEvent(new PointerEvent("pointerdown", options));
      receiver.dispatchEvent(new PointerEvent("pointerup", options));
    } catch (_error) {
    }
    receiver.dispatchEvent(new MouseEvent("mouseover", options));
    receiver.dispatchEvent(new MouseEvent("mousedown", options));
    receiver.dispatchEvent(new MouseEvent("mouseup", options));
    receiver.dispatchEvent(new MouseEvent("click", options));
    try {
      receiver.click();
    } catch (_error) {
    }
    return true;
  };
  const dispatchPointClickNoScroll = (x, y) => {
    const pointed = document.elementFromPoint(
      Math.max(1, Math.min(window.innerWidth - 1, x)),
      Math.max(1, Math.min(window.innerHeight - 1, y))
    );
    const target = actionTargetOf(pointed);
    return dispatchClickNoScroll(target || pointed, pointed);
  };
  const dispatchPointClickCascadeNoScroll = (x, y) => {
    const safeX = Math.max(1, Math.min(window.innerWidth - 1, x));
    const safeY = Math.max(1, Math.min(window.innerHeight - 1, y));
    const pointed = document.elementFromPoint(safeX, safeY);
    if (!pointed || !visible(pointed)) return false;
    const targets = [];
    const pushTarget = (el) => {
      if (el && !targets.includes(el) && visible(el) && !disabledState(el)) targets.push(el);
    };
    pushTarget(pointed);
    pushTarget(actionTargetOf(pointed));
    for (let current = pointed.parentElement, depth = 0; current && current !== document.body && depth < 8; current = current.parentElement, depth += 1) {
      pushTarget(current);
    }
    const options = {bubbles: true, cancelable: true, view: window, clientX: safeX, clientY: safeY};
    for (const target of targets) {
      try {
        target.dispatchEvent(new PointerEvent("pointerdown", options));
        target.dispatchEvent(new PointerEvent("pointerup", options));
      } catch (_error) {
      }
      target.dispatchEvent(new MouseEvent("mouseover", options));
      target.dispatchEvent(new MouseEvent("mousedown", options));
      target.dispatchEvent(new MouseEvent("mouseup", options));
      target.dispatchEvent(new MouseEvent("click", options));
      try {
        target.click();
      } catch (_error) {
      }
    }
    return targets.length > 0;
  };
  const clickEl = (el) => {
    const target = actionTargetOf(el);
    return dispatchClick(target, el);
  };
  const clickAny = (el) => {
    const target = actionTargetOf(el);
    return dispatchClick(target, el);
  };
  const clickDirectAny = (el) => {
    const target = actionTargetOf(el);
    return dispatchClickNoScroll(target, el);
  };
  const isDisabled = (el) => {
    const target = actionTargetOf(el);
    return !target || disabledState(target);
  };
  const rememberCopiedText = (value) => {
    const text = String(value || "").trim();
    if (!text) return;
    window.__wawaCredentialCopiedTexts = window.__wawaCredentialCopiedTexts || [];
    window.__wawaCredentialCopiedTexts.push(text);
    if (window.__wawaCredentialCopiedTexts.length > 16) {
      window.__wawaCredentialCopiedTexts = window.__wawaCredentialCopiedTexts.slice(-16);
    }
  };
  const installClipboardCapture = () => {
    if (window.__wawaCredentialClipboardCaptureInstalled) return;
    window.__wawaCredentialClipboardCaptureInstalled = true;
    window.__wawaCredentialCopiedTexts = window.__wawaCredentialCopiedTexts || [];
    try {
      const clipboard = navigator.clipboard;
      if (clipboard && typeof clipboard.writeText === "function") {
        const originalWriteText = clipboard.writeText.bind(clipboard);
        Object.defineProperty(clipboard, "writeText", {
          configurable: true,
          value: (value) => {
            rememberCopiedText(value);
            return originalWriteText(value);
          },
        });
      }
    } catch (_error) {
    }
    try {
      document.addEventListener("copy", (event) => {
        try {
          const data = event.clipboardData ? event.clipboardData.getData("text/plain") : "";
          if (data) rememberCopiedText(data);
        } catch (_error) {
        }
      }, true);
    } catch (_error) {
    }
  };
  installClipboardCapture();
  const byText = (labels, root = document) => {
    const candidates = Array.from(root.querySelectorAll("button,a,[role='button'],[class*='button'],[class*='btn'],.ant-btn,.el-button,.veui-button,span,div"));
    for (const label of labels) {
      const matches = [];
      for (const el of candidates) {
        const text = textOf(el) || String(el.getAttribute("aria-label") || el.getAttribute("title") || "").trim();
        const target = clickableOf(el);
        if (!text) continue;
        const matched = text === label || (text.includes(label) && text.length <= Math.max(80, label.length + 30));
        if (!matched) continue;
        const box = el.getBoundingClientRect();
        if (box.width > 340 || box.height > 100) continue;
        matches.push({el, exact: text === label ? 1 : 0, clickable: target ? 1 : 0, area: box.width * box.height});
      }
      matches.sort((a, b) => b.exact - a.exact || b.clickable - a.clickable || a.area - b.area);
      for (const match of matches) {
        if (!isDisabled(match.el) && clickAny(match.el)) return label;
      }
    }
    return "";
  };
  const isProtectedCredentialDialog = (text) => /下载访问密钥|下载凭证|查看密钥详情|Access\s*Key\s*创建成功|Secret\s*Key|SecretAccessKey|访问密钥ID|Access\s*Key\s*ID|AccessKeyID|Security\s*Key|AK\/SK/i.test(text);
  const nuisanceDialogPattern = /满意度评价|非常不满意|非常满意|开始评价|The number of ak has reached the maximum|ak has reached the maximum|访问密钥.*(?:已达|达到).*(?:上限|最大)|(?:上限|最大).*访问密钥/i;
  const dismissNuisanceDialogs = () => {
    const roots = Array.from(document.querySelectorAll(
      "[role='dialog'],.ant-modal,.ant-modal-content,.ant-message,.ant-message-notice,.ant-notification,.ant-notification-notice,.el-message,.el-notification,.veui-toast,div"
    )).filter((el) => {
      if (!visible(el)) return false;
      const text = textOf(el);
      if (!nuisanceDialogPattern.test(text) || isProtectedCredentialDialog(text)) return false;
      const box = el.getBoundingClientRect();
      if (box.width < 120 || box.height < 32) return false;
      if (box.width > window.innerWidth * 0.98 || box.height > window.innerHeight * 0.98) return false;
      return true;
    }).sort((a, b) => {
      const ab = a.getBoundingClientRect();
      const bb = b.getBoundingClientRect();
      return (ab.width * ab.height) - (bb.width * bb.height);
    });
    for (const root of roots) {
      if (byText(["关闭全部"], root)) return true;
      const rootBox = root.getBoundingClientRect();
      const closers = Array.from(root.querySelectorAll("button,a,[role='button'],svg,i,span,div"))
        .filter((el) => {
          if (!visible(el) || disabledState(el)) return false;
          const box = el.getBoundingClientRect();
          if (box.width < 8 || box.height < 8 || box.width > 70 || box.height > 70) return false;
          const text = textOf(el);
          const meta = [text, el.getAttribute("aria-label") || "", el.getAttribute("title") || "", String(el.className || ""), String(el.id || "")].join(" ");
          const nearRightTop = box.left >= rootBox.left + rootBox.width * 0.58 && box.top <= rootBox.top + Math.max(86, rootBox.height * 0.35);
          return /关闭|close|dismiss|remove|clear|×|x/i.test(meta) || (nearRightTop && /^[×x]?$/.test(text));
        })
        .sort((a, b) => {
          const ab = a.getBoundingClientRect();
          const bb = b.getBoundingClientRect();
          const ar = Math.abs((rootBox.right - ab.right)) + Math.abs((ab.top - rootBox.top));
          const br = Math.abs((rootBox.right - bb.right)) + Math.abs((bb.top - rootBox.top));
          return ar - br;
        });
      for (const closer of closers) {
        if (clickAny(closer)) return true;
      }
    }
    return false;
  };
  const rowsWith = (regex) => Array.from(document.querySelectorAll("tr,[role='row'],.ant-table-row,.el-table__row,.arco-table-tr,.arco-table-row"))
    .filter((row) => visible(row) && regex.test(textOf(row)));
  const ctyunAccessKeyRows = () => rowsWith(/\b[a-fA-F0-9]{32}\b/)
    .filter((row) => {
      const rowText = textOf(row);
      if (/回收时间|清理时间|回收站|恢复/.test(rowText)) return false;
      return /已启用|已禁用/.test(rowText);
    });
  const firstToken = (text, regex) => {
    const match = String(text || "").match(regex);
    return match ? match[0] : "";
  };
  const rowDate = (row) => {
    const match = textOf(row).match(/20\d{2}[/-]\d{1,2}[/-]\d{1,2}(?:\s+\d{1,2}:\d{1,2}(?::\d{1,2})?)?/);
    if (!match) return Number.MAX_SAFE_INTEGER;
    const value = Date.parse(match[0].replace(/\//g, "-"));
    return Number.isFinite(value) ? value : Number.MAX_SAFE_INTEGER;
  };
  const earliestRow = (rows) => {
    if (!rows.length) return null;
    return rows.slice().sort((a, b) => rowDate(a) - rowDate(b))[0] || rows[rows.length - 1];
  };
  const modalTextPattern = /新增访问密钥|删除访问密钥|下载访问密钥|下载凭证|停用访问密钥|请输入\s*(?:DELETE|YES)|完整输入|确认创建|Access\s*Key\s*创建成功|查看密钥详情|Secret\s*Key|SecretAccessKey/i;
  const dialogRoots = () => {
    const roots = Array.from(document.querySelectorAll("[role='dialog'],.ant-modal,.ant-modal-content,.el-dialog,.veui-dialog,.arco-modal,.arco-modal-content,.arco-dialog,.arco-dialog-content")).filter(visible);
    const candidates = Array.from(document.querySelectorAll("div,section,article"))
      .filter((el) => {
        if (!visible(el)) return false;
        const text = textOf(el);
        if (!modalTextPattern.test(text)) return false;
        if (!/(取消|确定|确认|下一步|一键输入|暂不下载|下载访问密钥|下载凭证|查看密钥详情|继续)/.test(text)) return false;
        const box = el.getBoundingClientRect();
        if (box.width < 280 || box.height < 120) return false;
        if (box.width > window.innerWidth * 0.94 || box.height > window.innerHeight * 0.96) return false;
        return true;
      });
    const unique = [];
    for (const root of roots.concat(candidates)) {
      if (!unique.includes(root)) unique.push(root);
    }
    return unique.sort((a, b) => {
      const ab = a.getBoundingClientRect();
      const bb = b.getBoundingClientRect();
      return (ab.width * ab.height) - (bb.width * bb.height);
    });
  };
  const activeDialogRoot = () => {
    const dialogs = dialogRoots();
    return dialogs[0] || document;
  };
  const fillDialogInput = (value) => {
    if (!value) return false;
    const root = activeDialogRoot();
    const inputs = Array.from(root.querySelectorAll("input,textarea")).filter((el) => visible(el) && !el.disabled && !el.readOnly);
    for (const input of inputs) {
      const meta = [input.name || "", input.id || "", input.placeholder || "", input.getAttribute("aria-label") || "", input.getAttribute("title") || ""].join(" ");
      const current = String(input.value || "");
      if (!current || /delete|yes|access\s*key|accesskey|访问密钥|id/i.test(meta) || inputs.length === 1) {
        input.focus();
        const prototype = Object.getPrototypeOf(input);
        const descriptor = prototype ? Object.getOwnPropertyDescriptor(prototype, "value") : null;
        if (descriptor && typeof descriptor.set === "function") {
          descriptor.set.call(input, value);
        } else {
          input.value = value;
        }
        try {
          input.setSelectionRange(value.length, value.length);
        } catch (_error) {
        }
        try {
          input.dispatchEvent(new InputEvent("input", {bubbles: true, inputType: "insertText", data: value}));
        } catch (_error) {
          input.dispatchEvent(new Event("input", {bubbles: true}));
        }
        input.dispatchEvent(new Event("change", {bubbles: true}));
        input.dispatchEvent(new KeyboardEvent("keyup", {bubbles: true, key: value.slice(-1) || ""}));
        return true;
      }
    }
    return false;
  };
  const dialogInputMatches = (pattern, root = activeDialogRoot()) => {
    const inputs = Array.from(root.querySelectorAll("input,textarea")).filter((el) => visible(el) && !el.disabled && !el.readOnly);
    return inputs.some((input) => pattern.test(String(input.value || "").trim()));
  };
  const scrollDialogToBottom = (root = activeDialogRoot()) => {
    let moved = false;
    const nodes = [root].concat(Array.from(root.querySelectorAll("*")));
    for (const node of nodes) {
      if (!visible(node)) continue;
      if (node.scrollHeight > node.clientHeight + 8) {
        node.scrollTop = node.scrollHeight;
        node.dispatchEvent(new Event("scroll", {bubbles: true}));
        moved = true;
      }
    }
    const visibleNodes = nodes.filter(visible);
    const last = visibleNodes[visibleNodes.length - 1];
    if (last && typeof last.scrollIntoView === "function") {
      try {
        last.scrollIntoView({block: "end", inline: "nearest"});
        moved = true;
      } catch (_error) {
      }
    }
    return moved;
  };
  const clickHuaweiSecretEye = (root = activeDialogRoot()) => {
    const rootText = textOf(root);
    if (!/下载访问密钥|Secret\s*Key|密钥/.test(rootText) || !/\*{4,}/.test(rootText)) return false;
    const anchors = Array.from(root.querySelectorAll("tr,[role='row'],div,p,span,label"))
      .filter((el) => visible(el) && (/Secret\s*Key/i.test(textOf(el)) || /\*{6,}/.test(textOf(el))));
    const candidates = Array.from(root.querySelectorAll("button,a,[role='button'],svg,i,span"))
      .filter((el) => visible(el));
    for (const anchor of anchors) {
      const ab = anchor.getBoundingClientRect();
      const amid = ab.top + ab.height / 2;
      const near = [];
      for (const el of candidates) {
        const box = el.getBoundingClientRect();
        const mid = box.top + box.height / 2;
        if (Math.abs(mid - amid) > 38) continue;
        if (box.width < 8 || box.height < 8 || box.width > 90 || box.height > 70) continue;
        if (box.left < ab.left + 70) continue;
        const meta = [textOf(el), el.getAttribute("aria-label") || "", el.getAttribute("title") || "", String(el.className || ""), String(el.id || "")].join(" ");
        if (/关闭|close/i.test(meta)) continue;
        const tag = String(el.tagName || "").toLowerCase();
        if (/eye|visible|visibility|show|查看|显示|明文|password|secret/i.test(meta) || tag === "svg" || tag === "i") {
          if (clickAny(el)) return true;
        }
        near.push({el, distance: Math.abs(mid - amid) + Math.max(0, box.left - ab.right) / 20, area: box.width * box.height});
      }
      near.sort((a, b) => a.distance - b.distance || a.area - b.area);
      for (const item of near.slice(0, 3)) {
        if (clickAny(item.el)) return true;
      }
    }
    return false;
  };
  const clickVolcSecretEye = () => {
    window.__wawaVolcKeyCopyState = window.__wawaVolcKeyCopyState || {ak: false, sk: false};
    const copyState = window.__wawaVolcKeyCopyState;
    const copiedTexts = Array.isArray(window.__wawaCredentialCopiedTexts)
      ? window.__wawaCredentialCopiedTexts.map((item) => String(item || "").trim()).filter(Boolean)
      : [];
    const looksLikeVolcAkText = (value) => /^AKLT[A-Za-z0-9+/=_-]{12,}$/.test(String(value || "").trim());
    const looksLikeCopiedVolcSecretText = (value) => {
      const text = String(value || "").trim();
      return /^[A-Za-z0-9+/=_-]{24,}$/.test(text) && !/^AKLT/i.test(text) && !/^[A-Fa-f0-9]{32}$/.test(text);
    };
    const looksLikeVisibleVolcSecretText = (value) => {
      const text = String(value || "").trim();
      if (!text || /\*{4,}/.test(text) || /AKLT[A-Za-z0-9+/=_-]{8,}/.test(text)) return false;
      return /[A-Za-z0-9+/=_-]{8,}(?:\.{3}|…)?/.test(text);
    };
    const isFullVolcSecretToken = (value) => {
      const text = String(value || "").trim();
      return /^[A-Za-z0-9+/=_-]{24,}$/.test(text)
        && !/^AKLT/i.test(text)
        && !/^HPUA/i.test(text)
        && !/^[A-Fa-f0-9]{32}$/.test(text)
        && !/[.*…]/.test(text);
    };
    const volcCredentialTextOf = (root) => {
      if (!root) return "";
      const values = [];
      const push = (value) => {
        const text = String(value || "").trim();
        if (text) values.push(text);
      };
      push(textOf(root));
      for (const node of [root].concat(Array.from(root.querySelectorAll("[title],[aria-label],[data-clipboard-text],[data-copy],input,textarea"))).slice(0, 80)) {
        push(node.getAttribute("title"));
        push(node.getAttribute("aria-label"));
        push(node.getAttribute("data-clipboard-text"));
        push(node.getAttribute("data-copy"));
        push(node.value);
      }
      return values.join("\n");
    };
    const firstVolcAkToken = (text) => {
      const match = String(text || "").match(/AKLT[A-Za-z0-9+/=_-]{12,}/);
      return match ? match[0] : "";
    };
    const firstFullVolcSecretToken = (text) => {
      const tokens = String(text || "").match(/[A-Za-z0-9+/=_-]{24,}/g) || [];
      return tokens.find(isFullVolcSecretToken) || "";
    };
    const externalCache = window.__wawaCredentialExternalCache || {};
    copyState.ak = Boolean(externalCache.ak) || copiedTexts.some(looksLikeVolcAkText);
    copyState.sk = Boolean(externalCache.sk) || copiedTexts.some(looksLikeCopiedVolcSecretText);
    const rejectDangerAction = (el) => {
      const meta = [
        textOf(el),
        el.getAttribute("aria-label") || "",
        el.getAttribute("title") || "",
        el.getAttribute("role") || "",
        String(el.className || ""),
        String(el.id || ""),
        String((el.parentElement && el.parentElement.className) || ""),
        String((el.outerHTML || "")).slice(0, 180),
      ].join(" ");
      return /删除|禁用|关闭|delete|disable|close/i.test(meta);
    };
    const volcEyeMetaText = (el) => [
      textOf(el),
      el.getAttribute("aria-label") || "",
      el.getAttribute("title") || "",
      el.getAttribute("role") || "",
      String(el.className || ""),
      String(el.id || ""),
      String((el.parentElement && el.parentElement.className) || ""),
      String((el.outerHTML || "")).slice(0, 220),
    ].join(" ");
    const isLikelyVolcEyeElement = (el) => {
      if (!el || !visible(el) || disabledState(el)) return false;
      const box = el.getBoundingClientRect();
      if (box.width < 6 || box.height < 6 || box.width > 90 || box.height > 80) return false;
      const meta = volcEyeMetaText(el);
      if (/删除|禁用|关闭|delete|disable|close/i.test(meta)) return false;
      const tag = String(el.tagName || "").toLowerCase();
      if (/eye|visible|visibility|show|显示|查看|明文|password|secret|preview/i.test(meta)) return true;
      return tag === "svg" || tag === "path" || tag === "use" || tag === "i";
    };
    const clickVolcEyeElement = (el) => {
      if (!isLikelyVolcEyeElement(el)) return false;
      const target = actionTargetOf(el) || el;
      const targetBox = target.getBoundingClientRect();
      if (!visible(target) || disabledState(target) || targetBox.width > 130 || targetBox.height > 90) {
        return dispatchClickNoScroll(el, el);
      }
      return dispatchClickNoScroll(target, el);
    };
    const clickVolcEyeAtPoint = (x, y, rowBox = null) => {
      const safeX = Math.max(1, Math.min(window.innerWidth - 1, x));
      const safeY = Math.max(1, Math.min(window.innerHeight - 1, y));
      const layers = typeof document.elementsFromPoint === "function"
        ? document.elementsFromPoint(safeX, safeY)
        : [document.elementFromPoint(safeX, safeY)];
      const seen = [];
      const pushCandidate = (el) => {
        for (let current = el, depth = 0; current && current !== document.body && depth < 5; current = current.parentElement, depth += 1) {
          if (!seen.includes(current)) seen.push(current);
        }
      };
      layers.filter(Boolean).forEach(pushCandidate);
      for (const el of seen) {
        if (clickVolcEyeElement(el)) return true;
      }
      const near = Array.from(document.querySelectorAll("button,a,[role='button'],span,div,svg,i,path,use,[class*='icon'],[class*='eye']"))
        .filter((el) => {
          if (!isLikelyVolcEyeElement(el)) return false;
          const box = el.getBoundingClientRect();
          const centerX = box.left + box.width / 2;
          const centerY = box.top + box.height / 2;
          if (Math.abs(centerY - safeY) > 24) return false;
          if (Math.abs(centerX - safeX) > 80) return false;
          if (rowBox) {
            if (centerX < rowBox.left + rowBox.width * 0.42) return false;
            if (centerX > rowBox.left + rowBox.width * 0.80) return false;
          }
          return true;
        })
        .map((el) => {
          const box = el.getBoundingClientRect();
          const centerX = box.left + box.width / 2;
          const centerY = box.top + box.height / 2;
          return {el, distance: Math.abs(centerX - safeX) + Math.abs(centerY - safeY), area: box.width * box.height};
        })
        .sort((a, b) => a.distance - b.distance || a.area - b.area);
      for (const item of near.slice(0, 5)) {
        if (clickVolcEyeElement(item.el)) return true;
      }
      return false;
    };
    const handleCreatedKeyDialog = () => {
      let root = activeDialogRoot();
      let rootText = textOf(root);
      if (!/Access\s*Key\s*创建成功/.test(rootText) && /Access\s*Key\s*创建成功/.test(bodyText)) {
        root = document;
        rootText = bodyText;
      }
      if (!/Access\s*Key\s*创建成功/.test(rootText)) return "";
      if (
        /Access\s*Key\s*ID|AccessKeyID/i.test(rootText) &&
        /Secret\s*Access\s*Key|SecretAccessKey/i.test(rootText)
      ) {
        return "volc-created-key-detail-visible";
      }
      const detailToggles = Array.from(root.querySelectorAll("button,a,[role='button'],span,div,p"))
        .filter((el) => {
          if (!visible(el) || isDisabled(el)) return false;
          const text = textOf(el);
          if (!text.includes("查看密钥详情") || text.length > 60) return false;
          const box = el.getBoundingClientRect();
          if (box.width < 20 || box.height < 12 || box.width > 380 || box.height > 70) return false;
          return true;
        })
        .sort((a, b) => {
          const ab = a.getBoundingClientRect();
          const bb = b.getBoundingClientRect();
          return (ab.width * ab.height) - (bb.width * bb.height);
      });
      for (const toggle of detailToggles) {
        if (clickDirectAny(toggle)) return "volc-show-created-key-detail";
      }
      if (byText(["查看密钥详情"], root)) return "volc-show-created-key-detail";
      return "";
    };
    const volcAccessKeyTableRoot = () => {
      const headings = Array.from(document.querySelectorAll("h1,h2,h3,h4,div,span,p"))
        .filter((el) => visible(el) && textOf(el) === "Access Key")
        .map((el) => ({el, box: el.getBoundingClientRect()}))
        .sort((a, b) => a.box.top - b.box.top);
      const apiHeading = Array.from(document.querySelectorAll("h1,h2,h3,h4,div,span,p"))
        .filter((el) => visible(el) && textOf(el) === "API Key")
        .map((el) => el.getBoundingClientRect())
        .sort((a, b) => a.top - b.top)[0] || null;
      const maxBottom = apiHeading ? apiHeading.top : window.innerHeight + 2000;
      const tableCandidates = Array.from(document.querySelectorAll("table,.arco-table,.arco-table-container,.arco-table-content,.ant-table,.el-table,[class*='table']"))
        .filter((el) => visible(el))
        .map((el) => ({el, box: el.getBoundingClientRect(), text: textOf(el)}))
        .filter((item) => item.box.height >= 40 && item.box.top < maxBottom && item.box.bottom > 120);
      for (const heading of headings) {
        const table = tableCandidates
          .filter((item) => item.box.top >= heading.box.top - 12 && item.box.top < maxBottom)
          .sort((a, b) => a.box.top - b.box.top || (a.box.width * a.box.height) - (b.box.width * b.box.height))[0];
        if (table) return table.el;
      }
      const fallbackTable = tableCandidates
        .filter((item) => /Access\s*Key\s*ID|Secret\s*Access\s*Key|SecretAccessKey|AKLT|暂无数据|EMPTY/i.test(item.text))
        .sort((a, b) => a.box.top - b.box.top)[0];
      return fallbackTable ? fallbackTable.el : null;
    };
    const volcSecretHeaderCell = () => {
      const table = volcAccessKeyTableRoot() || document;
      const headerNodes = Array.from(table.querySelectorAll("th,[role='columnheader'],.arco-table-th,.arco-table-cell,.ant-table-cell,span,div"))
        .filter((el) => {
          if (!visible(el)) return false;
          const text = textOf(el);
          if (!/Secret\s*Access\s*Key/i.test(text)) return false;
          const box = el.getBoundingClientRect();
          if (box.height > 90 || box.width > 520) return false;
          return true;
        });
      const cells = headerNodes
        .map((el) => el.closest("th,[role='columnheader'],.arco-table-th,.arco-table-cell,.ant-table-cell") || el)
        .filter((el, index, list) => el && list.indexOf(el) === index)
        .map((el) => ({el, box: el.getBoundingClientRect(), area: el.getBoundingClientRect().width * el.getBoundingClientRect().height}))
        .filter((item) => item.box.width >= 80 && item.box.width <= 520 && item.box.height >= 12 && item.box.height <= 90)
        .sort((a, b) => a.area - b.area);
      return cells.length ? cells[0].el : null;
    };
    const clickCreateAccessKeyWhenEmpty = () => {
      if (!/Access\s*Key/i.test(bodyText) || !/创建\s*Access\s*Key/i.test(bodyText)) return "";
      if (rowsWith(/AKLT[A-Za-z0-9+/=_-]{8,}/).length) {
        window.__wawaVolcAccessKeyEmptySeen = 0;
        return "";
      }
      const table = volcAccessKeyTableRoot();
      if (!table) {
        window.__wawaVolcAccessKeyEmptySeen = 0;
        return "";
      }
      const tableText = textOf(table);
      if (/AKLT[A-Za-z0-9+/=_-]{8,}/.test(tableText) || /\*{4,}/.test(tableText)) {
        window.__wawaVolcAccessKeyEmptySeen = 0;
        return "";
      }
      if (!/(暂无数据|EMPTY|No\s*Data|无数据)/i.test(tableText)) {
        window.__wawaVolcAccessKeyEmptySeen = 0;
        return "";
      }
      window.__wawaVolcAccessKeyEmptySeen = (Number(window.__wawaVolcAccessKeyEmptySeen || 0) || 0) + 1;
      if (window.__wawaVolcAccessKeyEmptySeen < 2) return "volc-wait-empty-access-key-table";
      if (byText(["创建 Access Key", "创建Access Key", "创建 AccessKey", "创建AccessKey"])) {
        window.__wawaVolcAccessKeyEmptySeen = 0;
        return "volc-create-access-key";
      }
      return "";
    };
    const createdKeyAction = handleCreatedKeyDialog();
    if (createdKeyAction) return createdKeyAction;
    const clickVisibleCopyNearToken = (kind) => {
      const tokenPattern = kind === "ak"
        ? /AKLT[A-Za-z0-9+/=_-]{8,}/
        : /[A-Za-z0-9+/=_-]{8,}(?:\.{3}|…)?/;
      const rawAnchors = Array.from(document.querySelectorAll("span,div,p,td,[role='cell'],.arco-table-td,.arco-table-cell,.ant-table-cell,.el-table__cell"))
        .filter((el) => {
          if (!visible(el)) return false;
          const text = textOf(el);
          if (!tokenPattern.test(text)) return false;
          if (kind === "sk" && /AKLT[A-Za-z0-9+/=_-]{8,}/.test(text)) return false;
          if (/\*{4,}/.test(text)) return false;
          const box = el.getBoundingClientRect();
          if (box.width < 28 || box.height < 8 || box.height > 80) return false;
          if (box.left < (kind === "ak" ? 240 : 430) || box.top < 100) return false;
          return true;
        });
      const anchors = rawAnchors
        .filter((el) => !Array.from(el.children || []).some((child) => visible(child) && tokenPattern.test(textOf(child))))
        .concat(rawAnchors)
        .filter((el, index, list) => list.indexOf(el) === index)
        .map((el) => ({el, box: el.getBoundingClientRect(), area: el.getBoundingClientRect().width * el.getBoundingClientRect().height}))
        .sort((a, b) => a.area - b.area || a.box.top - b.box.top);
      const candidates = Array.from(document.querySelectorAll("button,a,[role='button'],span,div,svg,i,path,use,[class*='icon'],[class*='copy']"))
        .filter((el) => {
          if (!visible(el) || isDisabled(el) || rejectDangerAction(el)) return false;
          const box = el.getBoundingClientRect();
          if (box.width < 6 || box.height < 6 || box.width > 70 || box.height > 70) return false;
          if (box.left < 260 || box.top < 100) return false;
          return true;
        });
      for (const anchor of anchors) {
        const ab = anchor.box;
        const centerY = ab.top + ab.height / 2;
        const near = candidates
          .map((el) => {
            const box = el.getBoundingClientRect();
            const meta = [
              textOf(el),
              el.getAttribute("aria-label") || "",
              el.getAttribute("title") || "",
              String(el.className || ""),
              String(el.id || ""),
              String((el.parentElement && el.parentElement.className) || ""),
              String((el.outerHTML || "")).slice(0, 180),
            ].join(" ");
            const centerX = box.left + box.width / 2;
            const yDistance = Math.abs((box.top + box.height / 2) - centerY);
            const xDistance = centerX - ab.right;
            const copyRank = /复制|copy|clipboard/i.test(meta) ? 0 : (/eye|visible|visibility|show|显示|查看|明文|password/i.test(meta) ? 2 : 1);
            return {el, copyRank, yDistance, xDistance, area: box.width * box.height};
          })
          .filter((item) => item.yDistance <= 24 && item.xDistance >= -12 && item.xDistance <= 170)
          .sort((a, b) => a.copyRank - b.copyRank || a.yDistance - b.yDistance || Math.abs(a.xDistance) - Math.abs(b.xDistance) || a.area - b.area);
        for (const item of near.slice(0, 4)) {
          if (clickDirectAny(item.el)) return true;
        }
      }
      return false;
    };
    const hasVisibleSecretToken = () => {
      return Array.from(document.querySelectorAll("span,div,p,td,[role='cell'],.arco-table-td,.arco-table-cell,.ant-table-cell,.el-table__cell"))
        .some((el) => {
          if (!visible(el)) return false;
          const text = textOf(el);
          if (/\*{4,}/.test(text) || /AKLT[A-Za-z0-9+/=_-]{8,}/.test(text)) return false;
          if (!looksLikeVisibleVolcSecretText(text)) return false;
          const box = el.getBoundingClientRect();
          if (box.left < 430 || box.top < 100 || box.width < 28 || box.height < 8 || box.height > 80) return false;
          return true;
        });
    };
    const clickVisibleEyeNearMask = () => {
      const rawMasks = Array.from(document.querySelectorAll("span,div,p,td,[role='cell'],.arco-table-td,.arco-table-cell,.ant-table-cell,.el-table__cell"))
        .filter((el) => {
          if (!visible(el)) return false;
          const text = textOf(el);
          if (!/\*{4,}/.test(text)) return false;
          const box = el.getBoundingClientRect();
          if (box.width < 24 || box.height < 8 || box.height > 80) return false;
          if (box.left < 220 || box.top < 100) return false;
          return true;
        });
      const masks = rawMasks
        .filter((el) => !Array.from(el.children || []).some((child) => visible(child) && /\*{4,}/.test(textOf(child))))
        .concat(rawMasks)
        .filter((el, index, list) => list.indexOf(el) === index)
        .map((el) => ({el, box: el.getBoundingClientRect(), area: el.getBoundingClientRect().width * el.getBoundingClientRect().height}))
        .sort((a, b) => a.area - b.area || a.box.top - b.box.top);
      const candidates = Array.from(document.querySelectorAll("button,a,[role='button'],span,div,svg,i,path,use,[class*='icon'],[class*='eye']"))
        .filter((el) => {
          if (!isLikelyVolcEyeElement(el)) return false;
          const box = el.getBoundingClientRect();
          if (box.left < 300 || box.top < 100) return false;
          return true;
        });
      for (const mask of masks) {
        const mb = mask.box;
        const centerY = mb.top + mb.height / 2;
        const near = candidates
          .map((el) => {
            const box = el.getBoundingClientRect();
            const meta = [
              textOf(el),
              el.getAttribute("aria-label") || "",
              el.getAttribute("title") || "",
              String(el.className || ""),
              String(el.id || ""),
              String((el.parentElement && el.parentElement.className) || ""),
              String((el.outerHTML || "")).slice(0, 180),
            ].join(" ");
            const centerX = box.left + box.width / 2;
            const yDistance = Math.abs((box.top + box.height / 2) - centerY);
            const xDistance = centerX - mb.right;
            const explicit = /eye|visible|visibility|show|显示|查看|明文|password|secret/i.test(meta) ? 0 : 1;
            return {el, box, explicit, yDistance, xDistance, area: box.width * box.height};
          })
          .filter((item) => item.yDistance <= 24 && item.xDistance >= -12 && item.xDistance <= 180)
          .sort((a, b) => a.explicit - b.explicit || a.yDistance - b.yDistance || Math.abs(a.xDistance) - Math.abs(b.xDistance) || a.area - b.area);
        for (const item of near.slice(0, 4)) {
          if (clickVolcEyeElement(item.el)) return true;
        }
        const xs = [mb.right + 14, mb.right + 26, mb.right + 42, mb.right + 66];
        for (const rawX of xs) {
          const x = Math.max(1, Math.min(window.innerWidth - 2, rawX));
          if (clickVolcEyeAtPoint(x, centerY)) return true;
        }
      }
      return false;
    };
    const clickAnyMaskedVolcRowEye = () => {
      const secretHeader = volcSecretHeaderCell();
      const secretHeaderBox = secretHeader ? secretHeader.getBoundingClientRect() : null;
      const rows = rowsWith(/AKLT[A-Za-z0-9+/=_-]{8,}/)
        .filter((row) => /\*{4,}/.test(textOf(row)));
      for (const row of rows) {
        const rowBox = row.getBoundingClientRect();
        if (rowBox.width < 300 || rowBox.height < 18) continue;
        const centerY = rowBox.top + rowBox.height / 2;
        if (secretHeaderBox) {
          const headerXs = [
            secretHeaderBox.left + secretHeaderBox.width * 0.72,
            secretHeaderBox.left + secretHeaderBox.width * 0.76,
            secretHeaderBox.left + secretHeaderBox.width * 0.68,
            secretHeaderBox.right - 78,
            secretHeaderBox.right - 56,
            secretHeaderBox.right - 34,
          ];
          for (const rawX of headerXs) {
            const x = Math.max(1, Math.min(window.innerWidth - 2, rawX));
            if (clickVolcEyeAtPoint(x, centerY, rowBox)) return true;
          }
        }
        const iconCandidates = Array.from(row.querySelectorAll("button,a,[role='button'],span,div,svg,i,path,use,[class*='icon'],[class*='eye']"))
          .filter((el) => {
            if (!visible(el) || isDisabled(el) || rejectDangerAction(el)) return false;
            const box = el.getBoundingClientRect();
            if (box.width < 6 || box.height < 6 || box.width > 80 || box.height > 80) return false;
            if (Math.abs((box.top + box.height / 2) - centerY) > 22) return false;
            const centerX = box.left + box.width / 2;
            if (centerX < rowBox.left + rowBox.width * 0.44) return false;
            if (centerX > rowBox.left + rowBox.width * 0.78) return false;
            return true;
          })
          .map((el) => {
            const box = el.getBoundingClientRect();
            const meta = [
              textOf(el),
              el.getAttribute("aria-label") || "",
              el.getAttribute("title") || "",
              String(el.className || ""),
              String(el.id || ""),
              String((el.parentElement && el.parentElement.className) || ""),
              String((el.outerHTML || "")).slice(0, 180),
            ].join(" ");
            const explicit = /eye|visible|visibility|show|显示|查看|明文|password|secret/i.test(meta) ? 0 : 1;
            const centerX = box.left + box.width / 2;
            const targetX = rowBox.left + rowBox.width * 0.60;
            return {el, explicit, distance: Math.abs(centerX - targetX), area: box.width * box.height};
          })
          .sort((a, b) => a.explicit - b.explicit || a.distance - b.distance || a.area - b.area);
        for (const item of iconCandidates.slice(0, 5)) {
          if (clickVolcEyeElement(item.el)) return true;
        }
        const xs = [
          rowBox.left + rowBox.width * 0.60,
          rowBox.left + rowBox.width * 0.58,
          rowBox.left + rowBox.width * 0.62,
          rowBox.left + rowBox.width * 0.56,
          rowBox.left + rowBox.width * 0.64,
        ];
        for (const rawX of xs) {
          const x = Math.max(1, Math.min(window.innerWidth - 2, rawX));
          if (clickVolcEyeAtPoint(x, centerY, rowBox)) return true;
        }
      }
      return false;
    };
    const clickCopyIconInCell = (cell) => {
      if (!cell || !visible(cell)) return false;
      const cellBox = cell.getBoundingClientRect();
      const candidates = Array.from(cell.querySelectorAll("button,a,[role='button'],span,div,svg,i,path,use,[class*='icon'],[class*='copy']"))
        .filter((el) => {
          if (!visible(el) || isDisabled(el)) return false;
          const box = el.getBoundingClientRect();
          if (box.width < 8 || box.height < 8 || box.width > 90 || box.height > 70) return false;
          if (box.left < cellBox.left + cellBox.width * 0.35) return false;
          const meta = [
            textOf(el),
            el.getAttribute("aria-label") || "",
            el.getAttribute("title") || "",
            el.getAttribute("role") || "",
            String(el.className || ""),
            String(el.id || ""),
            String((el.parentElement && el.parentElement.className) || ""),
            String((el.outerHTML || "")).slice(0, 180),
          ].join(" ");
          if (rejectDangerAction(el)) return false;
          return true;
        })
        .map((el) => {
          const box = el.getBoundingClientRect();
          const meta = [
            textOf(el),
            el.getAttribute("aria-label") || "",
            el.getAttribute("title") || "",
            String(el.className || ""),
            String(el.id || ""),
            String((el.parentElement && el.parentElement.className) || ""),
            String((el.outerHTML || "")).slice(0, 180),
          ].join(" ");
          const copyRank = /复制|copy|clipboard/i.test(meta) ? 0 : (/eye|visible|visibility|show|显示|查看|明文|password/i.test(meta) ? 2 : 1);
          return {el, copyRank, left: box.left, area: box.width * box.height};
        })
        .sort((a, b) => a.copyRank - b.copyRank || a.left - b.left || a.area - b.area);
      for (const item of candidates.slice(0, 4)) {
        if (clickDirectAny(item.el)) return true;
      }
      return false;
    };
    const clickVisibleVolcRowCopy = () => {
      const rows = rowsWith(/AKLT[A-Za-z0-9+/=_-]{8,}/);
      for (const row of rows) {
        const rowText = textOf(row);
        if (/\*{4,}/.test(rowText)) continue;
        const cells = Array.from(row.querySelectorAll("td,[role='cell'],.arco-table-td,.arco-table-cell,.ant-table-cell,.el-table__cell"))
          .filter(visible);
        const akCell = cells.find((cell) => /AKLT[A-Za-z0-9+/=_-]{8,}/.test(textOf(cell)));
        const secretCell = cells.find((cell) => {
          const cellText = textOf(cell);
          return !/\*{4,}/.test(cellText) && !/AKLT[A-Za-z0-9+/=_-]{8,}/.test(cellText) && looksLikeVisibleVolcSecretText(cellText);
        });
        if (!akCell || !secretCell) continue;
        const visibleAk = firstVolcAkToken(volcCredentialTextOf(akCell));
        const visibleSk = firstFullVolcSecretToken(volcCredentialTextOf(secretCell));
        if (visibleAk && visibleSk) {
          rememberCopiedText(visibleAk);
          rememberCopiedText(visibleSk);
          copyState.ak = true;
          copyState.sk = true;
          return "volc-read-visible-row";
        }
        if (!copyState.ak && clickCopyIconInCell(akCell)) {
          copyState.ak = true;
          return "volc-copy-ak";
        }
        if (!copyState.sk && clickCopyIconInCell(secretCell)) {
          copyState.sk = true;
          return "volc-copy-secret";
        }
        return "volc-visible-secret-retry-copy";
      }
      return "";
    };
    const visibleRowCopyAction = clickVisibleVolcRowCopy();
    if (visibleRowCopyAction) return visibleRowCopyAction;
    if (clickAnyMaskedVolcRowEye()) {
      copyState.eyeOpened = true;
      return "volc-show-any-row-secret";
    }
    if (clickVisibleEyeNearMask()) {
      copyState.eyeOpened = true;
      return "volc-show-visible-secret";
    }
    if (!copyState.ak && clickVisibleCopyNearToken("ak")) {
      copyState.ak = true;
      return "volc-copy-ak";
    }
    if (!copyState.sk && clickVisibleCopyNearToken("sk")) {
      copyState.sk = true;
      return "volc-copy-secret";
    }
    const rows = rowsWith(/AKLT[A-Za-z0-9+/=_-]{10,}/);
    for (const row of rows) {
      const rowText = textOf(row);
      const cells = Array.from(row.querySelectorAll("td,[role='cell'],.arco-table-td,.arco-table-cell,.ant-table-cell,.el-table__cell"))
        .filter(visible);
      const akCell = cells.find((cell) => /AKLT[A-Za-z0-9+/=_-]{8,}/.test(textOf(cell)));
      let secretCell = cells.find((cell) => /\*{4,}/.test(textOf(cell)));
      if (!secretCell) {
        secretCell = cells.find((cell) => {
          const cellText = textOf(cell);
          return looksLikeVisibleVolcSecretText(cellText);
        }) || null;
      }
      if (akCell && !copyState.ak && clickCopyIconInCell(akCell)) {
        copyState.ak = true;
        return "volc-copy-ak";
      }
      if (!secretCell) continue;
      const secretText = textOf(secretCell);
      if (!/\*{4,}/.test(secretText) && looksLikeVisibleVolcSecretText(secretText)) {
        if (!copyState.sk && clickCopyIconInCell(secretCell)) {
          copyState.sk = true;
          return "volc-copy-secret";
        }
        continue;
      }
      const masks = Array.from(secretCell.querySelectorAll("span,div,p"))
        .filter((el) => visible(el) && /\*{4,}/.test(textOf(el)));
      if (!masks.length && /\*{4,}/.test(textOf(secretCell))) masks.push(secretCell);
      const maskBox = masks.length ? masks[0].getBoundingClientRect() : secretCell.getBoundingClientRect();
      const maskIsWholeCell = masks[0] === secretCell;
      const cellBox = secretCell.getBoundingClientRect();
      const clickByPoint = () => {
        const centerY = maskBox.top + maskBox.height / 2;
        const xs = [
          Math.min(cellBox.right - 14, maskBox.right + 18),
          cellBox.right - 18,
          cellBox.left + cellBox.width * 0.72,
        ];
        for (const rawX of xs) {
          const x = Math.max(cellBox.left + 8, Math.min(cellBox.right - 8, rawX));
          if (clickVolcEyeAtPoint(x, centerY)) return true;
        }
        return false;
      };
      if (clickByPoint()) {
        copyState.eyeOpened = true;
        return true;
      }
      const candidates = Array.from(secretCell.querySelectorAll("button,a,[role='button'],span,div,svg,i,path,use,[class*='icon'],[class*='eye']"))
        .filter((el) => {
          if (!isLikelyVolcEyeElement(el)) return false;
          const box = el.getBoundingClientRect();
          const centerY = box.top + box.height / 2;
          if (Math.abs(centerY - (maskBox.top + maskBox.height / 2)) > 28) return false;
          if (maskIsWholeCell) {
            if (box.left < maskBox.left + maskBox.width * 0.45) return false;
          } else if (box.left < maskBox.right - 4) {
            return false;
          }
          const meta = [
            textOf(el),
            el.getAttribute("aria-label") || "",
            el.getAttribute("title") || "",
            el.getAttribute("role") || "",
            String(el.className || ""),
            String(el.id || ""),
            String((el.parentElement && el.parentElement.className) || ""),
            String((el.outerHTML || "")).slice(0, 180),
          ].join(" ");
          return true;
        })
        .map((el) => {
          const box = el.getBoundingClientRect();
          const meta = [
            textOf(el),
            el.getAttribute("aria-label") || "",
            el.getAttribute("title") || "",
            String(el.className || ""),
            String(el.id || ""),
            String((el.parentElement && el.parentElement.className) || ""),
            String((el.outerHTML || "")).slice(0, 180),
          ].join(" ");
          const explicit = /显示|查看|明文|eye|visible|visibility|show|secret|password/i.test(meta) ? 0 : 1;
          const distance = Math.abs((box.top + box.height / 2) - (maskBox.top + maskBox.height / 2)) + Math.max(0, box.left - maskBox.right) / 8;
          return {el, explicit, distance, area: box.width * box.height};
        })
        .sort((a, b) => a.explicit - b.explicit || a.distance - b.distance || a.area - b.area);
      for (const item of candidates.slice(0, 4)) {
        if (clickVolcEyeElement(item.el)) {
          copyState.eyeOpened = true;
          return true;
        }
      }
    }
    if (hasVisibleSecretToken()) return "volc-visible-secret-retry-copy";
    if (copyState.eyeOpened) return "volc-eye-opened-retry-copy";
    const createAccessKeyAction = clickCreateAccessKeyWhenEmpty();
    if (createAccessKeyAction) return createAccessKeyAction;
    return false;
  };
  const clickCheckboxNear = (patterns, root = activeDialogRoot()) => {
    const rootText = textOf(root);
    const rootMatches = patterns.some((pattern) => pattern.test(rootText));
    const markNativeChecked = (box) => {
      try {
        const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(box), "checked");
        if (descriptor && typeof descriptor.set === "function") {
          descriptor.set.call(box, true);
        } else {
          box.checked = true;
        }
      } catch (_error) {
        box.checked = true;
      }
      box.dispatchEvent(new Event("input", {bubbles: true}));
      box.dispatchEvent(new Event("change", {bubbles: true}));
    };
    const boxes = Array.from(root.querySelectorAll("input[type='checkbox']")).filter((el) => !el.disabled);
    for (const box of boxes) {
      const wrapper = box.closest("label,.ant-checkbox-wrapper,.el-checkbox,.veui-checkbox") || box.closest(".ant-checkbox") || box.parentElement || box;
      const text = textOf(wrapper);
      if (!patterns.some((pattern) => rootMatches || pattern.test(text))) continue;
      if (box.checked) return "checked";
      if (wrapper && visible(wrapper)) {
        clickAny(wrapper);
      } else {
        clickAny(box);
      }
      markNativeChecked(box);
      return "clicked";
    }
    const customBoxes = Array.from(root.querySelectorAll("[role='checkbox'],.ant-checkbox,.el-checkbox,.veui-checkbox,[class*='checkbox']"))
      .filter((el) => visible(el) && !disabledState(el));
    for (const box of customBoxes) {
      const text = textOf(box.closest("label,.ant-checkbox-wrapper,.el-checkbox,.veui-checkbox,div") || box);
      if (!patterns.some((pattern) => rootMatches || pattern.test(text))) continue;
      if (box.getAttribute("aria-checked") === "true" || /\bchecked\b/.test(String(box.className || ""))) return "checked";
      if (clickAny(box)) return "clicked";
    }
    const labelTargets = Array.from(root.querySelectorAll("label,span,div,p"))
      .filter((el) => visible(el) && patterns.some((pattern) => pattern.test(textOf(el))));
    for (const label of labelTargets) {
      if (clickAny(label)) return "clicked";
    }
    return "";
  };
  const bodyText = textOf(document.body);
  if (dismissNuisanceDialogs()) return "dismiss-nuisance-dialog";
  window.__wawaCredentialOldestDeleted = window.__wawaCredentialOldestDeleted || {};
  window.__wawaCredentialDeleteConsent = window.__wawaCredentialDeleteConsent || {};
  window.__wawaCredentialDeleteCancel = window.__wawaCredentialDeleteCancel || {};
  const deleteStateKey = "__wawaCredentialOldestDeleted_" + vendor;
  const deleteConsentKey = "__wawaCredentialDeleteConsent_" + vendor;
  const deleteCancelKey = "__wawaCredentialDeleteCancel_" + vendor;
  const oldestDeleted = () => {
    let stored = false;
    try {
      stored = sessionStorage.getItem(deleteStateKey) === "1";
    } catch (_error) {
    }
    return Boolean(window.__wawaCredentialOldestDeleted[vendor]) || stored;
  };
  const markOldestDeleted = () => {
    window.__wawaCredentialOldestDeleted[vendor] = true;
    try {
      sessionStorage.setItem(deleteStateKey, "1");
    } catch (_error) {
    }
  };
  const deleteConsent = () => {
    let stored = false;
    try {
      stored = sessionStorage.getItem(deleteConsentKey) === "1";
    } catch (_error) {
    }
    return Boolean(window.__wawaCredentialDeleteConsent[vendor]) || stored;
  };
  const deleteCancelled = () => {
    let stored = false;
    try {
      stored = sessionStorage.getItem(deleteCancelKey) === "1";
    } catch (_error) {
    }
    return Boolean(window.__wawaCredentialDeleteCancel[vendor]) || stored;
  };
  const markDeleteConsent = () => {
    window.__wawaCredentialDeleteConsent[vendor] = true;
    window.__wawaCredentialDeleteCancel[vendor] = false;
    try {
      sessionStorage.setItem(deleteConsentKey, "1");
      sessionStorage.removeItem(deleteCancelKey);
    } catch (_error) {
    }
  };
  const markDeleteCancelled = () => {
    window.__wawaCredentialDeleteCancel[vendor] = true;
    try {
      sessionStorage.setItem(deleteCancelKey, "1");
    } catch (_error) {
    }
  };
  const showDeleteConsentDialog = () => {
    if (document.getElementById("wawa-credential-delete-consent-dialog")) return true;
    const overlay = document.createElement("div");
    overlay.id = "wawa-credential-delete-consent-dialog";
    overlay.style.cssText = [
      "position:fixed",
      "inset:0",
      "z-index:2147483647",
      "background:rgba(15,23,42,.34)",
      "display:flex",
      "align-items:center",
      "justify-content:center",
      "font-family:'Microsoft YaHei',Arial,sans-serif"
    ].join(";");
    const panel = document.createElement("div");
    panel.style.cssText = [
      "width:430px",
      "max-width:calc(100vw - 48px)",
      "background:#fff",
      "border-radius:8px",
      "box-shadow:0 18px 46px rgba(15,23,42,.24)",
      "overflow:hidden",
      "border:1px solid rgba(15,23,42,.12)"
    ].join(";");
    const title = document.createElement("div");
    title.textContent = "AK/SK访问密钥";
    title.style.cssText = "background:#ed1029;color:#fff;font-size:14px;font-weight:600;padding:10px 16px;";
    const body = document.createElement("div");
    body.textContent = "发现两个AK/SK访问密钥，当前无法使用和新建，是否删除最早的AK/SK访问密钥并创建新的？";
    body.style.cssText = "padding:26px 22px 20px;color:#111827;font-size:15px;line-height:1.7;text-align:left;";
    const buttons = document.createElement("div");
    buttons.style.cssText = "display:flex;gap:12px;justify-content:center;padding:0 20px 24px;";
    const makeButton = (label, action, primary) => {
      const button = document.createElement("button");
      button.type = "button";
      button.textContent = label;
      button.style.cssText = [
        "min-width:120px",
        "height:34px",
        "border-radius:4px",
        "font-size:14px",
        "cursor:pointer",
        primary ? "background:#ed1029;color:#fff;border:1px solid #ed1029" : "background:#fff;color:#111827;border:1px solid #c9cdd4"
      ].join(";");
      button.onclick = () => {
        if (action === "delete") {
          markDeleteConsent();
        } else {
          markDeleteCancelled();
        }
        overlay.remove();
      };
      return button;
    };
    buttons.appendChild(makeButton("删除", "delete", true));
    buttons.appendChild(makeButton("取消", "cancel", false));
    panel.appendChild(title);
    panel.appendChild(body);
    panel.appendChild(buttons);
    overlay.appendChild(panel);
    document.documentElement.appendChild(overlay);
    return true;
  };

  if (vendor === "huawei") {
    if (!/console\.huaweicloud\.com/.test(location.host + location.href)) return "";
    if (/下载访问密钥|Secret\s*Key/i.test(bodyText) && clickHuaweiSecretEye(activeDialogRoot())) {
      return "huawei-show-secret";
    }
    if (/新增访问密钥/.test(bodyText) && /我理解上述建议|继续创建访问密钥|使用建议/.test(bodyText)) {
      const root = activeDialogRoot();
      const scrolled = scrollDialogToBottom(root);
      const checkboxResult = clickCheckboxNear([/我理解上述建议/, /继续创建访问密钥/, /使用建议/], root);
      if (checkboxResult === "clicked") return "huawei-create-check";
      if (checkboxResult === "checked" && byText(["下一步"], root)) return "huawei-create-next";
      if (scrolled) return "huawei-create-scroll";
    }
    if (/删除访问密钥|永久删除访问密钥|请输入\s*DELETE|完整输入.*DELETE/i.test(bodyText)) {
      const root = activeDialogRoot();
      if (!dialogInputMatches(/^DELETE$/i, root)) {
        const clickedAutofill = byText(["一键输入"], root);
        if (clickedAutofill) return "huawei-delete-autofill";
        if (fillDialogInput("DELETE")) return "huawei-delete-fill";
      }
      if (byText(["确定", "确认"], root)) {
        markOldestDeleted();
        return "huawei-delete-confirm";
      }
    }
    if (/请输入.*yes|输入.*yes|键入.*yes|确认创建|继续创建访问密钥/i.test(bodyText)) {
      const root = activeDialogRoot();
      if (!dialogInputMatches(/^YES$/i, root)) {
        const clickedAutofill = byText(["一键输入"], root);
        if (clickedAutofill) return "huawei-create-yes-autofill";
        if (fillDialogInput("YES")) return "huawei-create-fill-yes";
      }
      if (byText(["确定", "确认"], root)) return "huawei-create-yes-confirm";
    }
    if (/停用访问密钥|删除访问密钥|此操作无法撤销|确认删除/.test(bodyText) && byText(["确定", "确认"])) return "huawei-confirm";
    const rows = rowsWith(/HPUA[A-Z0-9]{12,}/);
    if (rows.length >= 2) {
      if (oldestDeleted()) return "huawei-wait-after-delete";
      if (deleteCancelled()) return "huawei-delete-cancelled";
      if (!deleteConsent()) {
        showDeleteConsentDialog();
        return "huawei-delete-consent";
      }
      const target = earliestRow(rows);
      if (target && byText(["删除"], target)) return "huawei-delete-oldest";
      if (target && byText(["停用"], target)) return "huawei-disable-oldest";
      return "";
    }
    if (rows.length < 2) {
      if (byText(["新增访问密钥", "创建访问密钥", "新增密钥"])) return "huawei-create";
      if (/新增访问密钥|创建访问密钥|访问密钥/.test(bodyText) && byText(["确定", "确认"])) return "huawei-create-confirm";
    }
    return "";
  }

  if (vendor === "ctyun") {
    if (!/iam\.ctyun\.cn/.test(location.host + location.href)) return "";
    const rows = ctyunAccessKeyRows();
    const target = earliestRow(rows);
    const targetKey = target ? firstToken(textOf(target), /\b[a-fA-F0-9]{32}\b/) : "";
    if (/确认禁用|禁用AccessKey|禁用\s*$/.test(bodyText) && byText(["确认", "确定"])) return "ctyun-disable-confirm";
    if (/确认删除|删除AccessKey|移入回收站|回收站/.test(bodyText)) {
      fillDialogInput(targetKey || firstToken(bodyText, /\b[a-fA-F0-9]{32}\b/));
      if (byText(["移入回收站", "确认", "确定"])) {
        markOldestDeleted();
        return "ctyun-delete-confirm";
      }
    }
    if (rows.length >= 2) {
      if (oldestDeleted()) return "ctyun-wait-after-delete";
      if (deleteCancelled()) return "ctyun-delete-cancelled";
      if (!deleteConsent()) {
        showDeleteConsentDialog();
        return "ctyun-delete-consent";
      }
      if (target && byText(["删除"], target)) return "ctyun-delete-oldest";
      if (target && byText(["禁用"], target)) return "ctyun-disable-oldest";
      return "";
    }
    if (rows.length < 2 && byText(["创建AccessKey", "创建 AccessKey", "创建Access Key"])) return "ctyun-create";
    return "";
  }

  if (vendor === "volc") {
    if (!/console\.volcengine\.com/.test(location.host + location.href)) return "";
    if (/安全风险提示/.test(bodyText)) {
      const root = activeDialogRoot();
      if (byText(["继续"], root)) return "volc-risk-continue";
      return "";
    }
    if (/验证码|安全验证|身份验证|二次验证/.test(bodyText) && /确认|确定|提交/.test(bodyText)) {
      return "";
    }
    const volcAction = clickVolcSecretEye();
    if (volcAction) return volcAction;
    const rows = rowsWith(/AKLT[A-Za-z0-9+/=_-]{10,}/);
    for (const row of rows) {
      const rowText = textOf(row);
      if (/Secret\s*Access\s*Key/i.test(rowText) && !/\*{4,}/.test(rowText)) continue;
      const candidates = Array.from(row.querySelectorAll("button,a,[role='button'],span,svg,i"));
      for (const el of candidates) {
        const meta = [textOf(el), el.getAttribute("aria-label") || "", el.getAttribute("title") || "", String(el.className || "")].join(" ");
        if (/显示|查看|明文|eye|visible|visibility|Secret/i.test(meta) || el.tagName.toLowerCase() === "svg") {
          if (!isDisabled(el) && clickDirectAny(el)) return "volc-show-secret";
        }
      }
    }
    return "";
  }
  return "";
})()
""".replace("__VENDOR__", vendor_json)


def _coerce_snapshot(raw: Any) -> dict[str, Any]:
    if isinstance(raw, dict):
        return raw
    if isinstance(raw, str):
        try:
            data = json.loads(raw)
        except Exception:
            return {"text": raw, "rows": [], "fields": []}
        return data if isinstance(data, dict) else {"text": raw, "rows": [], "fields": []}
    return {"text": str(raw or ""), "rows": [], "fields": []}


def _read_system_clipboard_text() -> str:
    try:
        import tkinter as tk

        root = tk.Tk()
        root.withdraw()
        try:
            return str(root.clipboard_get() or "").strip()
        finally:
            root.destroy()
    except Exception:
        return ""


def _looks_like_volc_clipboard_token(value: str, kind: str) -> bool:
    token = clean_key_token(value)
    if not token or "*" in token or "..." in token or "…" in token or any(ch.isspace() for ch in token):
        return False
    upper = token.upper()
    if kind == "ak":
        return upper.startswith("AKLT") and len(token) >= 16
    if kind == "sk":
        return len(token) >= 24 and not upper.startswith(("HPUA", "AKLT")) and not is_hex_id(token)
    return False


def _capture_web_login_clipboard(vendor: str, action: Any, page_copied_values: Any = None) -> dict[str, str]:
    cache = _WEB_LOGIN_CLIPBOARD_CACHE.setdefault(vendor, {})
    action_text = str(action or "")
    if vendor != "volc":
        return dict(cache)
    if isinstance(page_copied_values, list):
        for item in reversed(page_copied_values):
            candidate = clean_key_token(str(item or ""))
            if _looks_like_volc_clipboard_token(candidate, "ak") and not cache.get("ak"):
                cache["ak"] = candidate
            elif _looks_like_volc_clipboard_token(candidate, "sk") and not cache.get("sk"):
                cache["sk"] = candidate
            if cache.get("ak") and cache.get("sk"):
                break
    if not action_text.startswith("volc-copy-"):
        return dict(cache)
    expected_kind = "ak" if action_text == "volc-copy-ak" else "sk"
    value = ""
    if isinstance(page_copied_values, list):
        for item in reversed(page_copied_values):
            candidate = clean_key_token(str(item or ""))
            if _looks_like_volc_clipboard_token(candidate, expected_kind):
                value = candidate
                break
    for _attempt in range(6):
        if value:
            break
        time.sleep(0.18)
        candidate = clean_key_token(_read_system_clipboard_text())
        if _looks_like_volc_clipboard_token(candidate, expected_kind):
            value = candidate
            break
    if expected_kind == "ak" and value:
        cache["ak"] = value
    elif expected_kind == "sk" and value:
        cache["sk"] = value
    return dict(cache)


def _field_block(snapshot: dict[str, Any]) -> str:
    lines = []
    for item in snapshot.get("fields") or []:
        if not isinstance(item, dict):
            continue
        meta = str(item.get("meta") or "").strip()
        value = str(item.get("value") or "").strip()
        if value:
            lines.append(f"{meta}\n{value}")
    return "\n".join(lines)


def _credential_blocks(snapshot: dict[str, Any]) -> list[str]:
    blocks: list[str] = []
    clipboard = snapshot.get("clipboard")
    if isinstance(clipboard, dict):
        ak = clean_key_token(str(clipboard.get("ak") or ""))
        sk = clean_key_token(str(clipboard.get("sk") or ""))
        if ak and sk:
            blocks.append(f"Access Key ID\n{ak}\nSecret Access Key\n{sk}")
    for row in snapshot.get("rows") or []:
        if not isinstance(row, dict):
            continue
        text = str(row.get("text") or "").strip()
        cells = row.get("cells") or []
        if isinstance(cells, list):
            cell_text = "\n".join(str(cell or "").strip() for cell in cells if str(cell or "").strip())
        else:
            cell_text = ""
        block = "\n".join(value for value in (text, cell_text) if value)
        if block:
            blocks.append(block)
    field_text = _field_block(snapshot)
    if field_text:
        blocks.append(field_text)
    full_text = "\n".join(
        value
        for value in (
            str(snapshot.get("title") or ""),
            str(snapshot.get("url") or ""),
            str(snapshot.get("text") or ""),
            field_text,
        )
        if value
    )
    if full_text:
        blocks.append(full_text)
    return blocks


def _parse_ctyun_keys(text: str) -> tuple[str, str]:
    text = text or ""
    create_dialog_re = re.compile(r"创建\s*AccessKey|创建\s*Access\s*Key|下载凭证|AccessKey\s*ID|SecurityKey", re.IGNORECASE)
    if create_dialog_re.search(text):
        secret_label_re = re.compile(r"Security\s*Key|SecurityKey|Secret\s*Key|SecretKey|访问密钥\s*SK|密钥\s*SK", re.IGNORECASE)
        ak_label_re = re.compile(r"Access\s*Key\s*ID|AccessKey\s*ID|AccessKeyID|访问密钥\s*(?:AK|ID)", re.IGNORECASE)
        for secret_match in reversed(list(secret_label_re.finditer(text))):
            secret_tail = text[secret_match.end() : secret_match.end() + 220]
            sk_match = CTYUN_KEY_RE.search(secret_tail)
            if not sk_match:
                continue
            sk = sk_match.group(0)
            head = text[max(0, secret_match.start() - 900) : secret_match.start()]
            ak_matches = list(ak_label_re.finditer(head))
            for ak_match in reversed(ak_matches):
                ak_tail = head[ak_match.end() : ak_match.end() + 220]
                ak_match_value = CTYUN_KEY_RE.search(ak_tail)
                if ak_match_value and ak_match_value.group(0) != sk:
                    return ak_match_value.group(0), sk

    table_like = re.search(r"创建时间|上次使用时间|操作|已启用|已禁用|回收时间|清理时间|回收站", text)
    ak, sk = ("", "") if table_like else extract_ak_sk(text)
    if ak and sk:
        return ak, sk

    lines = [line.strip() for line in (text or "").splitlines() if line.strip()]

    def after_label(patterns: tuple[str, ...]) -> str:
        label_re = re.compile("|".join(patterns), re.IGNORECASE)
        for index, line in enumerate(lines):
            match = label_re.search(line)
            if not match:
                continue
            same_line = line[match.end() :]
            key_match = CTYUN_KEY_RE.search(same_line)
            if key_match:
                return key_match.group(0)
            for next_line in lines[index + 1 : index + 8]:
                if AK_LABEL_RE.search(next_line) or SK_LABEL_RE.search(next_line):
                    break
                key_match = CTYUN_KEY_RE.search(next_line)
                if key_match:
                    return key_match.group(0)
        return ""

    explicit_ak = after_label((r"Access\s*Key\s*ID", r"AccessKey\s*ID", r"AccessKeyID", r"访问密钥\s*(?:AK|ID)"))
    explicit_sk = after_label((r"Security\s*Key", r"SecurityKey", r"Secret\s*Key", r"SecretKey", r"访问密钥\s*SK", r"密钥\s*SK"))
    if explicit_ak and explicit_sk and explicit_ak != explicit_sk:
        return explicit_ak, explicit_sk

    if table_like:
        return explicit_ak, explicit_sk

    if AK_LABEL_RE.search(text) and SK_LABEL_RE.search(text) and len(text) <= 1200:
        candidates = CTYUN_KEY_RE.findall(text)
        if len(candidates) == 2:
            return candidates[-2], candidates[-1]
    return explicit_ak, explicit_sk


def _parse_keys_for_vendor(text: str, vendor: str) -> tuple[str, str]:
    if vendor == "ctyun":
        return _parse_ctyun_keys(text)
    return extract_ak_sk(text)


def _valid_web_login_pair(vendor: str, ak: str, sk: str, block: str) -> bool:
    ak = clean_key_token(ak)
    sk = clean_key_token(sk)
    if not ak or not sk or ak == sk:
        return False
    if not AK_LABEL_RE.search(block) or not SK_LABEL_RE.search(block):
        return False
    ak_upper = ak.upper()
    sk_upper = sk.upper()
    if vendor == "huawei":
        if not ak_upper.startswith("HPUA"):
            return False
        if sk_upper.startswith(("HPUA", "AKLT")) or is_hex_id(sk):
            return False
        if HUAWEI_MASKED_SECRET_RE.search(block):
            unmasked_secret_re = re.compile(
                r"(?:Security\s*Key|Secret\s*Access\s*Key|SecretAccessKey|Secret\s*Key|SecretKey|密钥)[\s:：\r\n]*"
                + re.escape(sk),
                re.IGNORECASE,
            )
            if not unmasked_secret_re.search(block):
                return False
        if HUAWEI_PAGE_SCRIPT_TOKEN_RE.search(sk):
            return False
        if not HUAWEI_SECRET_VALUE_RE.fullmatch(sk):
            return False
        return True
    if vendor == "volc":
        if not ak_upper.startswith("AKLT"):
            return False
        if sk_upper.startswith(("HPUA", "AKLT")) or is_hex_id(sk):
            return False
        return len(sk) >= 24
    if vendor == "ctyun":
        return bool(CTYUN_KEY_RE.fullmatch(ak) and CTYUN_KEY_RE.fullmatch(sk))
    return False


def _extract_credentials_from_snapshot(snapshot: dict[str, Any], vendor: str) -> tuple[str, str, str]:
    for block in _credential_blocks(snapshot):
        ak, sk = _parse_keys_for_vendor(block, vendor)
        if _valid_web_login_pair(vendor, ak, sk, block):
            clipboard_block = block.startswith("Access Key ID\n") and "\nSecret Access Key\n" in block
            mark = "" if clipboard_block else extract_mark(block, vendor)
            if not mark:
                mark = extract_mark(str(snapshot.get("text") or ""), vendor)
            return clean_key_token(ak), clean_key_token(sk), mark
    return "", "", ""


def _read_page_snapshot(window: Any, vendor: str) -> dict[str, Any]:
    action = ""
    try:
        if vendor == "volc":
            external_cache = json.dumps(_WEB_LOGIN_CLIPBOARD_CACHE.get(vendor, {}), ensure_ascii=False)
            window.evaluate_js(f"window.__wawaCredentialExternalCache = {external_cache};")
        action = window.evaluate_js(_page_automation_script(vendor)) or ""
    except Exception:
        pass
    raw = window.evaluate_js(_page_snapshot_script()) or ""
    snapshot = _coerce_snapshot(raw)
    clipboard = _capture_web_login_clipboard(vendor, action, snapshot.get("pageClipboard"))
    if clipboard:
        snapshot["clipboard"] = clipboard
    return snapshot


def _close_page_prompt_script() -> str:
    return r"""
(() => {
  const old = document.getElementById("wawa-credential-close-dialog");
  if (old) {
    old.remove();
  }
  window.__wawaCredentialCloseDecision = "";
  const overlay = document.createElement("div");
  overlay.id = "wawa-credential-close-dialog";
  overlay.style.cssText = [
    "position:fixed",
    "inset:0",
    "z-index:2147483647",
    "background:rgba(0,0,0,.22)",
    "display:flex",
    "align-items:center",
    "justify-content:center",
    "font-family:'Microsoft YaHei',Arial,sans-serif"
  ].join(";");
  const panel = document.createElement("div");
  panel.style.cssText = [
    "width:390px",
    "max-width:calc(100vw - 48px)",
    "background:#fff",
    "border-radius:8px",
    "box-shadow:0 18px 46px rgba(15,23,42,.24)",
    "overflow:hidden",
    "border:1px solid rgba(15,23,42,.12)"
  ].join(";");
  const title = document.createElement("div");
  title.textContent = "AK/SK密钥提取完毕";
  title.style.cssText = "background:#ed1029;color:#fff;font-size:14px;font-weight:600;padding:10px 16px;";
  const body = document.createElement("div");
  body.textContent = "请确认余额是否足够并预留流量费用；\n已提取AK/SK密钥，是否关闭页面？";
  body.style.cssText = "padding:26px 22px 20px;color:#111827;font-size:15px;line-height:1.7;text-align:left;white-space:pre-line;";
  const buttons = document.createElement("div");
  buttons.style.cssText = "display:flex;gap:12px;justify-content:center;padding:0 20px 24px;";
  const makeButton = (label, decision, primary) => {
    const button = document.createElement("button");
    button.type = "button";
    button.textContent = label;
    button.style.cssText = [
      "min-width:120px",
      "height:34px",
      "border-radius:4px",
      "font-size:14px",
      "cursor:pointer",
      primary ? "background:#ed1029;color:#fff;border:1px solid #ed1029" : "background:#fff;color:#111827;border:1px solid #c9cdd4"
    ].join(";");
    button.onclick = () => {
      window.__wawaCredentialCloseDecision = decision;
      overlay.remove();
    };
    return button;
  };
  buttons.appendChild(makeButton("关闭", "close", true));
  buttons.appendChild(makeButton("不关闭", "keep", false));
  panel.appendChild(title);
  panel.appendChild(body);
  panel.appendChild(buttons);
  overlay.appendChild(panel);
  document.documentElement.appendChild(overlay);
  return true;
})()
"""


def _ask_close_extracted_page(window: Any) -> bool:
    try:
        window.evaluate_js(_close_page_prompt_script())
        while True:
            time.sleep(0.2)
            decision = str(window.evaluate_js("window.__wawaCredentialCloseDecision || ''") or "").strip()
            if decision == "close":
                return True
            if decision == "keep":
                return False
    except Exception:
        pass
    try:
        return bool(window.create_confirmation_dialog("AK/SK密钥提取完毕", "请确认余额是否足够并预留流量费用；\n已提取AK/SK密钥，是否关闭页面？"))
    except Exception:
        return True


def _poll_page_for_credentials(window: Any, vendor: str, write_result: Any) -> None:
    _WEB_LOGIN_CLIPBOARD_CACHE[vendor] = {}
    while True:
        time.sleep(1.0)
        try:
            snapshot = _read_page_snapshot(window, vendor)
        except Exception:
            continue
        ak, sk, mark = _extract_credentials_from_snapshot(snapshot, vendor)
        if not ak or not sk:
            continue
        write_result({"ok": True, "vendor": vendor, "ak": ak, "sk": sk, "mark": mark})
        if _ask_close_extracted_page(window):
            try:
                window.destroy()
            except Exception:
                pass
        return


def _window_icon_path(vendor: str) -> str | None:
    filename = CLOUD_CREDENTIAL_WINDOW_ICONS.get(vendor)
    if not filename:
        return None
    path = Path(resource_path(filename))
    return str(path) if path.exists() else None


def _run_webview(vendor: str, result_path: Path | None) -> int:
    result_written = {"value": False}

    def write_result(data: dict[str, Any]) -> None:
        result_written["value"] = True
        _write_result(result_path, data)

    try:
        import webview
    except Exception:
        write_result({"ok": False, "message": WEBVIEW_IMPORT_MISSING_MESSAGE})
        return 1

    url = CLOUD_CREDENTIAL_PAGE_URLS.get(vendor, "")
    if not url:
        write_result({"ok": False, "message": "未知云厂商，无法打开 AK/SK 登录页。"})
        return 1

    cloud_name = CLOUD_CREDENTIAL_PAGE_NAMES.get(vendor, "云")
    window = webview.create_window(f"{cloud_name}登录获取AK/SK", url, width=1180, height=820)
    start_kwargs = {"gui": "edgechromium", "debug": False}
    icon_path = _window_icon_path(vendor)
    if icon_path:
        start_kwargs["icon"] = icon_path

    def on_started() -> None:
        threading.Thread(target=_poll_page_for_credentials, args=(window, vendor, write_result), daemon=True).start()

    try:
        webview.start(on_started, **start_kwargs)
    except Exception:
        write_result({"ok": False, "message": WEBVIEW2_MISSING_MESSAGE})
        return 1

    if not result_written["value"]:
        write_result({"ok": False, "message": "网页登录窗口已关闭，未提取到完整 AK/SK。"})
        return 1
    return 0


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument("vendor")
    parser.add_argument("result_path")
    args = parser.parse_args(argv)
    vendor = str(args.vendor or "").strip().lower()
    result_target = str(args.result_path or "").strip()
    result_path = None if result_target == "-" else Path(result_target).resolve()
    try:
        return _run_webview(vendor, result_path)
    except Exception as exc:
        _write_result(result_path, {"ok": False, "message": f"网页登录组件运行失败：{exc}"})
        return 1


if __name__ == "__main__":
    raise SystemExit(main(sys.argv[1:]))
