import { registerAs } from "@nestjs/config";

const normalizeAiProvider = (): "ollama" | "claude" | "openai" => {
  const provider = process.env.AI_PROVIDER?.trim().toLowerCase();

  if (!provider) {
    return "ollama";
  }

  if (provider !== "ollama" && provider !== "claude" && provider !== "openai") {
    return "ollama";
  }

  return provider;
};

const parseValkeyUrl = (url: string): { host?: string; port?: number; password?: string } => {
  try {
    const parsed = new URL(url);
    const port = parsed.port ? parseInt(parsed.port, 10) : undefined;

    return {
      host: parsed.hostname || undefined,
      port: Number.isNaN(port) ? undefined : port,
      password: parsed.password ? decodeURIComponent(parsed.password) : undefined,
    };
  } catch {
    return {};
  }
};

export const orchestratorConfig = registerAs("orchestrator", () => {
  const valkeyUrl = process.env.VALKEY_URL ?? "redis://localhost:6379";
  const parsedValkeyUrl = parseValkeyUrl(valkeyUrl);

  return {
    host: process.env.HOST ?? process.env.BIND_ADDRESS ?? "127.0.0.1",
    port: parseInt(process.env.ORCHESTRATOR_PORT ?? "3001", 10),
    valkey: {
      host: process.env.VALKEY_HOST ?? parsedValkeyUrl.host ?? "localhost",
      port: parseInt(process.env.VALKEY_PORT ?? String(parsedValkeyUrl.port ?? 6379), 10),
      password: process.env.VALKEY_PASSWORD ?? parsedValkeyUrl.password,
      url: valkeyUrl,
      connectTimeout: parseInt(process.env.VALKEY_CONNECT_TIMEOUT_MS ?? "5000", 10),
      commandTimeout: parseInt(process.env.VALKEY_COMMAND_TIMEOUT_MS ?? "3000", 10),
    },
    claude: {
      apiKey: process.env.CLAUDE_API_KEY,
    },
    aiProvider: normalizeAiProvider(),
    docker: {
      socketPath: process.env.DOCKER_SOCKET ?? "/var/run/docker.sock",
    },
    git: {
      userName: process.env.GIT_USER_NAME ?? "Mosaic Orchestrator",
      userEmail: process.env.GIT_USER_EMAIL ?? "orchestrator@mosaicstack.dev",
    },
    killswitch: {
      enabled: process.env.KILLSWITCH_ENABLED === "true",
    },
    sandbox: {
      enabled: process.env.SANDBOX_ENABLED !== "false",
      defaultImage: process.env.SANDBOX_DEFAULT_IMAGE ?? "node:20-alpine",
      defaultMemoryMB: parseInt(process.env.SANDBOX_DEFAULT_MEMORY_MB ?? "256", 10),
      defaultCpuLimit: parseFloat(process.env.SANDBOX_DEFAULT_CPU_LIMIT ?? "1.0"),
      networkMode: process.env.SANDBOX_NETWORK_MODE ?? "none",
    },
    coordinator: {
      url: process.env.COORDINATOR_URL ?? "http://localhost:8000",
      timeout: parseInt(process.env.COORDINATOR_TIMEOUT_MS ?? "30000", 10),
      retries: parseInt(process.env.COORDINATOR_RETRIES ?? "3", 10),
      apiKey: process.env.COORDINATOR_API_KEY,
    },
    yolo: {
      enabled: process.env.YOLO_MODE === "true",
    },
    spawner: {
      maxConcurrentAgents: parseInt(process.env.MAX_CONCURRENT_AGENTS ?? "2", 10),
      sessionCleanupDelayMs: parseInt(process.env.SESSION_CLEANUP_DELAY_MS ?? "30000", 10),
    },
    queue: {
      name: process.env.ORCHESTRATOR_QUEUE_NAME ?? "orchestrator-tasks",
      maxRetries: parseInt(process.env.ORCHESTRATOR_QUEUE_MAX_RETRIES ?? "3", 10),
      baseDelay: parseInt(process.env.ORCHESTRATOR_QUEUE_BASE_DELAY_MS ?? "1000", 10),
      maxDelay: parseInt(process.env.ORCHESTRATOR_QUEUE_MAX_DELAY_MS ?? "60000", 10),
      concurrency: parseInt(process.env.ORCHESTRATOR_QUEUE_CONCURRENCY ?? "1", 10),
      completedRetentionCount: parseInt(process.env.QUEUE_COMPLETED_RETENTION_COUNT ?? "100", 10),
      completedRetentionAgeSeconds: parseInt(
        process.env.QUEUE_COMPLETED_RETENTION_AGE_S ?? "3600",
        10
      ),
      failedRetentionCount: parseInt(process.env.QUEUE_FAILED_RETENTION_COUNT ?? "1000", 10),
      failedRetentionAgeSeconds: parseInt(process.env.QUEUE_FAILED_RETENTION_AGE_S ?? "86400", 10),
    },
  };
});
