import { access, readFile } from 'node:fs/promises';
import { constants } from 'node:fs';
import { resolve } from 'node:path';
import * as z from 'zod/v4';

const configSchema = z.object({
  backend: z.enum(['auto', 'x11', 'wayland']).default('auto'),
  x11: z.object({
    display: z.string().min(1).nullable().default(null),
  }).default({ display: null }),
  wayland: z.object({
    helperPath: z.string().min(1).nullable().default(null),
    portalTimeoutMs: z.number().int().positive().max(300_000).default(120_000),
    frameTimeoutMs: z.number().int().positive().max(30_000).default(5_000),
  }).default({ helperPath: null, portalTimeoutMs: 120_000, frameTimeoutMs: 5_000 }),
  observe: z.object({
    enabled: z.boolean().default(true),
    maxImageBytes: z.number().int().positive().max(64 * 1024 * 1024).default(12 * 1024 * 1024),
  }).default({ enabled: true, maxImageBytes: 12 * 1024 * 1024 }),
  action: z.object({
    enabled: z.boolean().default(true),
    maxTextBytes: z.number().int().positive().max(1024 * 1024).default(64 * 1024),
    maxScrollSteps: z.number().int().positive().max(1000).default(100),
  }).default({ enabled: true, maxTextBytes: 64 * 1024, maxScrollSteps: 100 }),
  logLevel: z.enum(['silent', 'info']).default('info'),
});

export type ChatGptComputerMcpConfig = z.infer<typeof configSchema>;

export function parseConfig(value: unknown): ChatGptComputerMcpConfig {
  return configSchema.parse(value);
}

async function exists(path: string): Promise<boolean> {
  try {
    await access(path, constants.R_OK);
    return true;
  } catch {
    return false;
  }
}

export async function loadConfig(): Promise<ChatGptComputerMcpConfig> {
  const explicit = process.env.CHATGPT_COMPUTER_MCP_CONFIG;
  const path = explicit === undefined ? resolve(process.cwd(), 'config.local.json') : resolve(explicit);
  if (!(await exists(path))) {
    if (explicit !== undefined) throw new Error(`CHATGPT_COMPUTER_MCP_CONFIG does not exist: ${path}`);
    return parseConfig({});
  }
  return parseConfig(JSON.parse(await readFile(path, 'utf8')) as unknown);
}
