(() => {
  if (window.MMWQianchuanOperationStateMachine) return;

  class OperationStateMachine {
    constructor(options = {}) {
      this.observe = options.observe;
      this.plan = options.plan;
      this.execute = options.execute;
      this.onStatus = typeof options.onStatus === "function" ? options.onStatus : () => {};
      this.wait = typeof options.wait === "function" ? options.wait : (ms) => new Promise((resolve) => setTimeout(resolve, ms));
      this.maxSteps = Math.max(1, Math.min(20, Number(options.maxSteps) || 12));
      this.timeoutMs = Math.max(5000, Math.min(120000, Number(options.timeoutMs) || 45000));
      this.stepTimeoutMs = Math.max(250, Math.min(30000, Number(options.stepTimeoutMs) || 15000));
      this.cancelled = false;
      this.cancelReason = "";
      this.running = false;
    }

    cancel(reason = "用户已停止 AI 接管") {
      this.cancelled = true;
      this.cancelReason = String(reason || "操作已取消");
    }

    async run(task = {}) {
      if (this.running) throw new Error("已有千川操作正在执行。");
      if (![this.observe, this.plan, this.execute].every((item) => typeof item === "function")) {
        throw new Error("千川接管状态机未完整加载。");
      }
      this.running = true;
      this.cancelled = false;
      this.cancelReason = "";
      const startedAt = Date.now();
      const audit = [];
      try {
        for (let step = 1; step <= this.maxSteps; step += 1) {
          this.assertActive(startedAt);
          this.onStatus({ phase: "observing", step, maxSteps: this.maxSteps, message: `正在重新识别页面（${step}/${this.maxSteps}）` });
          const observation = await this.runTimedStep(
            "页面识别",
            () => this.observe(task, { step, audit: [...audit] }),
            startedAt
          );
          this.assertSafeObservation(observation);
          this.assertActive(startedAt);
          const decision = await this.runTimedStep(
            "单步规划",
            () => this.plan(task, observation, { step, audit: [...audit] }),
            startedAt
          );
          if (decision?.done) {
            this.onStatus({ phase: "completed", step, message: decision.message || "目标状态已验证" });
            return { ok: true, steps: audit.length, observation, audit, result: decision.result || {} };
          }
          if (!decision?.action) throw new Error("当前页面无法规划下一步，AI 接管已安全停止。");
          this.onStatus({ phase: "acting", step, message: decision.message || "正在执行单步操作" });
          const result = await this.runTimedStep(
            "页面操作",
            () => this.execute(decision.action, task, observation, { step, audit: [...audit] }),
            startedAt
          );
          audit.push({
            step,
            action: decision.action.type,
            at: Date.now(),
            plannerSource: decision.plannerSource || "local",
            visualUsed: decision.visualUsed === true,
            plannerTokens: Math.max(0, Number(decision.plannerTokens) || 0),
            pageFingerprint: String(observation?.pageFingerprint || "").slice(0, 64),
            result: compactResult(result)
          });
          this.assertActive(startedAt);
          await this.wait(Math.max(250, Math.min(3000, Number(decision.waitMs) || 700)));
        }
        throw new Error(`已达到 ${this.maxSteps} 步安全上限，目标状态仍未验证。`);
      } finally {
        this.running = false;
      }
    }

    assertActive(startedAt) {
      if (this.cancelled) throw new Error(this.cancelReason || "操作已取消。");
      if (Date.now() - startedAt > this.timeoutMs) throw new Error("AI 接管操作超时，已安全停止。");
    }

    async runTimedStep(label, operation, startedAt) {
      this.assertActive(startedAt);
      const remaining = this.timeoutMs - (Date.now() - startedAt);
      const timeoutMs = Math.max(1, Math.min(this.stepTimeoutMs, remaining));
      let timer = null;
      try {
        return await Promise.race([
          Promise.resolve().then(operation),
          new Promise((_, reject) => {
            timer = setTimeout(() => reject(new Error(`${label}超时，AI 接管已安全停止。`)), timeoutMs);
          })
        ]);
      } finally {
        if (timer) clearTimeout(timer);
      }
    }

    assertSafeObservation(observation = {}) {
      const blocker = String(observation.blocker || "").trim();
      if (blocker) throw new Error(blocker);
      const text = String(observation.securityText || "");
      if (/验证码|滑块验证|扫码登录|重新登录|安全校验|风险验证|人脸验证/.test(text)) {
        throw new Error("检测到登录或平台安全校验，AI 接管已停止，请由你本人完成验证。");
      }
    }
  }

  function compactResult(value) {
    if (!value || typeof value !== "object") return {};
    return Object.fromEntries(Object.entries(value).filter(([key]) => !/text|html|snapshot/i.test(key)).slice(0, 12));
  }

  window.MMWQianchuanOperationStateMachine = Object.freeze({ OperationStateMachine });
})();
