import { randomUUID } from "node:crypto";

import type { WorkbenchApplication, WorkbenchCommand, WorkbenchCommandResult, WorkbenchMode, WorkbenchTemporalGateway } from "./contracts.ts";

const SESSION_ID = /^ses_[A-Za-z0-9._:-]{3,180}$/u;
const TRACE_ID = /^trc_[A-Za-z0-9._:-]{3,180}$/u;

export function createWorkbenchDispatcher(options: {
  application: WorkbenchApplication;
  temporal: WorkbenchTemporalGateway;
  mode: WorkbenchMode;
}) {
  return async function dispatch(command: WorkbenchCommand): Promise<WorkbenchCommandResult> {
    try {
      if (command.operation === "health") {
        return success(command.operation, options.mode, await options.application.health());
      }
      requireActor(command.actor);
      if (command.operation === "session.create") {
        return success(command.operation, options.mode, await options.application.createSession(command));
      }
      if (command.operation === "turn.submit") {
        const traceId = validId(command.traceId ?? `trc_${randomUUID()}`, TRACE_ID, "traceId");
        const sessionId = validId(command.params.sessionId, SESSION_ID, "sessionId");
        const admitted = await options.application.admitTurn({ actor: command.actor, traceId, sessionId, params: { ...command.params, traceId, sessionId } });
        const workflow = await options.temporal.submit(admitted);
        return success(command.operation, options.mode, {
          accepted: true,
          status: "running",
          traceId,
          sessionId,
          ...workflow,
          terminalAuthority: "hwlab.event.v1",
          resultSynthesized: false
        });
      }
      const traceId = validId(command.traceId, TRACE_ID, "traceId");
      const workflow = await options.temporal.cancel({ actor: command.actor, traceId, params: command.params ?? {} });
      return success(command.operation, options.mode, {
        accepted: true,
        status: "cancel_requested",
        traceId,
        ...workflow,
        terminalAuthority: "hwlab.event.v1",
        resultSynthesized: false
      });
    } catch (error: any) {
      return {
        ok: false,
        operation: command.operation,
        mode: options.mode,
        error: { code: error?.code ?? "workbench_command_failed", message: error?.message ?? String(error), details: error?.details }
      };
    }
  };
}

function success(operation: WorkbenchCommand["operation"], mode: WorkbenchMode, data: Record<string, unknown>): WorkbenchCommandResult {
  return { ok: true, operation, mode, data };
}

function requireActor(actor: { id?: string } | undefined) {
  if (!String(actor?.id ?? "").trim()) throw codedError("auth_required", "actor.id is required");
}

function validId(value: unknown, pattern: RegExp, field: string) {
  const text = String(value ?? "").trim();
  if (!pattern.test(text)) throw codedError("invalid_input", `${field} is invalid`, { field });
  return text;
}

function codedError(code: string, message: string, details?: unknown) {
  return Object.assign(new Error(message), { code, details });
}
