import { Effect } from "effect";

import { OrbConfigurationError } from "./domain";
import type { OrbModelGatewayConfig, OrbProjectContext } from "./domain";

// ---------------------------------------------------------------------------
// OpenCode configuration — prepared inside the AgentOS VM filesystem
// ---------------------------------------------------------------------------

const OPENCODE_CONFIG_DIR = "/root/.config/opencode";
const OPENCODE_CONFIG_PATH = `${OPENCODE_CONFIG_DIR}/config.json`;
const AGENT_INSTRUCTIONS_PATH = "/workspace/control/issue.md";

export interface PreparedOpenCodeConfig {
  readonly configJson: string;
  readonly configPath: string;
  readonly instructionsPath: string;
}

const validateGateway = (
  gateway: OrbModelGatewayConfig
): Effect.Effect<void, OrbConfigurationError> =>
  gateway.baseUrl.trim().length === 0
    ? Effect.fail(
        new OrbConfigurationError({
          message: "Model gateway base URL must not be empty",
          reason: "InvalidModelConfig",
        })
      )
    : Effect.void;

/**
 * Build the OpenCode configuration JSON and file layout for one Orb run.
 * The configuration points OpenCode at the model gateway with run-scoped
 * credentials injected at runtime — never committed to project files.
 */
export const prepareOpenCodeConfig = Effect.fn("Orb.prepareOpenCodeConfig")(
  function* prepareOpenCodeConfig(input: {
    readonly context: OrbProjectContext;
    readonly gateway: OrbModelGatewayConfig;
  }) {
    yield* validateGateway(input.gateway);

    const config = {
      $schema: "https://opencode.ai/config.json",
      model: `${input.gateway.provider}/${input.gateway.model}`,
      provider: {
        [input.gateway.provider]: {
          apiKey: input.gateway.apiKey,
          baseUrl: input.gateway.baseUrl,
          models: {
            [input.gateway.model]: {
              name: input.gateway.model,
            },
          },
        },
      },
    };

    const configJson = JSON.stringify(config, null, 2);

    return {
      configJson,
      configPath: OPENCODE_CONFIG_PATH,
      instructionsPath: AGENT_INSTRUCTIONS_PATH,
    } satisfies PreparedOpenCodeConfig;
  }
);

/** Shell commands that stage the OpenCode config directory inside a VM. */
export const opencodeSetupCommands = (config: PreparedOpenCodeConfig) =>
  [
    `mkdir -p ${OPENCODE_CONFIG_DIR}`,
    `cat > ${config.configPath} << 'ORB_EOF'\n${config.configJson}\nORB_EOF`,
    `chmod 600 ${config.configPath}`,
  ] as const;
