import type { BrowserContext, Page } from "playwright";
import { ExecutionLayer } from "@/workers/rpa/kernel/execution-layer";
import { SelectorGraph } from "@/workers/rpa/kernel/selector-graph";
import { StateEngine } from "@/workers/rpa/kernel/state-engine";
import {
  assertPlaywrightPage,
  assertRPAContext,
  isRPAContext,
  type IRPAContext,
} from "@/workers/rpa/kernel/context-validator";

export type { IRPAContext } from "@/workers/rpa/kernel/context-validator";

/** RPA 运行期唯一状态容器（无模块级全局变量） */
export class RPAContext implements IRPAContext {
  readonly selectors: SelectorGraph;
  readonly exec: ExecutionLayer;
  readonly runtime: ExecutionLayer;
  readonly state: StateEngine;
  private widgetScrollAtMs = 0;

  constructor(
    readonly page: Page,
    readonly browserContext?: BrowserContext,
  ) {
    assertPlaywrightPage(page, "RPAContext.constructor(page)");
    this.selectors = new SelectorGraph();
    this.exec = ExecutionLayer.forPage(page);
    this.runtime = this.exec;
    this.state = new StateEngine(this);
    assertRPAContext(this, "RPAContext.constructor");
  }

  static fromSession(
    pageOrCtx: Page | RPAContext,
    browserContext?: BrowserContext,
  ): RPAContext {
    return resolveRPAContext(pageOrCtx, browserContext);
  }

  getWidgetScrollAt(): number {
    return this.widgetScrollAtMs;
  }

  setWidgetScrollAt(ms: number): void {
    this.widgetScrollAtMs = ms;
  }
}

/** Page | RPAContext 统一解析（禁止把 Context 再包一层导致 page.locator 断裂） */
export function resolveRPAContext(
  pageOrCtx: Page | RPAContext,
  browserContext?: BrowserContext,
): RPAContext {
  if (isRPAContext(pageOrCtx)) {
    assertRPAContext(pageOrCtx);
    return pageOrCtx as RPAContext;
  }

  assertPlaywrightPage(pageOrCtx, "resolveRPAContext(page)");
  const created = new RPAContext(pageOrCtx, browserContext);
  assertRPAContext(created, "RPAContext.fromSession");
  return created;
}
