import { createRequire } from 'node:module';
import * as os from 'node:os';
import * as path from 'node:path';

import { MacpRuntime } from './macp-runtime.js';

// Resolve OC plugin SDK dynamically — works on any machine with openclaw installed globally
const ocRequire = createRequire(import.meta.url);
const sdkRoot = path.dirname(ocRequire.resolve('openclaw/dist/plugin-sdk/index.js'));

// Dynamic imports for runtime SDK functions
const { registerAcpRuntimeBackend, unregisterAcpRuntimeBackend } = (await import(
  `${sdkRoot}/acp-runtime.js`
)) as {
  registerAcpRuntimeBackend: (backend: {
    id: string;
    runtime: any;
    healthy: () => boolean;
  }) => void;
  unregisterAcpRuntimeBackend: (id: string) => void;
};

type PluginConfig = {
  defaultModel?: string;
  systemPrompt?: string;
  timeoutMs?: number;
  logDir?: string;
  repoRoot?: string;
  orchDir?: string;
  defaultDispatch?: string;
  defaultRuntime?: string;
};

function expandHome(rawPath: string): string {
  if (rawPath === '~') {
    return os.homedir();
  }
  if (rawPath.startsWith('~/')) {
    return path.join(os.homedir(), rawPath.slice(2));
  }
  return rawPath;
}

function resolveConfig(pluginConfig?: Record<string, unknown>, stateDir?: string) {
  const config = (pluginConfig ?? {}) as PluginConfig;
  const repoRoot = config.repoRoot?.trim()
    ? path.resolve(expandHome(config.repoRoot))
    : path.resolve(os.homedir(), 'src', 'mosaic-stack');
  return {
    defaultModel: config.defaultModel?.trim() || 'openai/gpt-5-mini',
    systemPrompt: config.systemPrompt ?? '',
    timeoutMs:
      typeof config.timeoutMs === 'number' &&
      Number.isFinite(config.timeoutMs) &&
      config.timeoutMs > 0
        ? config.timeoutMs
        : 300_000,
    stateDir: config.logDir?.trim()
      ? path.resolve(expandHome(config.logDir))
      : (stateDir ?? process.cwd()),
    repoRoot,
    orchDir: config.orchDir?.trim()
      ? path.resolve(expandHome(config.orchDir))
      : path.join(repoRoot, '.mosaic', 'orchestrator'),
    defaultDispatch: config.defaultDispatch?.trim() || 'yolo',
    defaultRuntime: config.defaultRuntime?.trim() || 'codex',
  };
}

function createMacpRuntimeService(pluginConfig?: Record<string, unknown>) {
  let runtime: MacpRuntime | null = null;

  return {
    id: 'macp-runtime',
    async start(ctx: { stateDir: string; logger: { info: (msg: string) => void } }) {
      const resolved = resolveConfig(pluginConfig, ctx.stateDir);
      runtime = new MacpRuntime({
        ...resolved,
        logger: ctx.logger,
      });
      registerAcpRuntimeBackend({
        id: 'macp',
        runtime,
        healthy: () => runtime !== null,
      });
      ctx.logger.info(
        `macp runtime backend registered (defaultRuntime: ${resolved.defaultRuntime}, defaultDispatch: ${resolved.defaultDispatch}, timeoutMs: ${resolved.timeoutMs})`,
      );
    },
    async stop() {
      if (runtime) {
        unregisterAcpRuntimeBackend('macp');
        runtime = null;
      }
    },
  };
}

export default function register(api: any) {
  const service = createMacpRuntimeService(api.pluginConfig);
  api.registerService(service);
}
