import {
  agentOS as createAgentOsActor,
  type AgentOSConfigInput,
} from "@rivet-dev/agentos";
import { Context, Effect, Layer, Schema } from "effect";

export class AgentOsError extends Schema.TaggedErrorClass<AgentOsError>()(
  "AgentOsError",
  {
    cause: Schema.Defect(),
  }
) {}

export interface AgentOsOptions {
  readonly config?: AgentOSConfigInput<undefined>;
}

export class AgentOs extends Context.Service<
  AgentOs,
  {
    readonly createActor: (
      config?: AgentOSConfigInput<undefined>
    ) => Effect.Effect<
      ReturnType<typeof createAgentOsActor<undefined>>,
      AgentOsError
    >;
  }
>()("@code/primitives/agent-os/AgentOs") {
  static readonly layer = Layer.succeed(
    AgentOs,
    AgentOs.of({
      createActor: Effect.fn("AgentOs.createActor")(function* (
        config: AgentOSConfigInput<undefined> = {}
      ) {
        return yield* Effect.try({
          try: () => createAgentOsActor<undefined>(config),
          catch: (cause) => new AgentOsError({ cause }),
        });
      }),
    })
  );
}

export const makeAgentOsLayer = (options: AgentOsOptions = {}) =>
  Layer.succeed(
    AgentOs,
    AgentOs.of({
      createActor: Effect.fn("AgentOs.createActor")(function* (
        config: AgentOSConfigInput<undefined> = options.config ?? {}
      ) {
        return yield* Effect.try({
          try: () => createAgentOsActor<undefined>(config),
          catch: (cause) => new AgentOsError({ cause }),
        });
      }),
    })
  );

export const createAgentOsActorEffect = Effect.fn("createAgentOsActorEffect")(
  function* (config?: AgentOSConfigInput<undefined>) {
    const agentOs = yield* AgentOs;
    return yield* agentOs.createActor(config);
  }
);
