import type { TestAgentFactory } from '@recombine-ai/engine'
import path from 'node:path'
import { pathToFileURL } from 'node:url'

export type BosunTestScope = 'global' | 'region'

export type BosunAgentMeta = {
	defaultRegion: string | null
	availableRegions: string[]
	testScope: BosunTestScope
}

export type BosunResolvedTestSuite = {
	suiteKey: string
	resolvedRegion: string | null
}

export interface BosunProjectApiV1 {
	version: 1
	getAgentMeta(agentId: string): Promise<BosunAgentMeta>
	resolveTestSuite(input: {
		agentId: string
		region?: string | null
	}): Promise<BosunResolvedTestSuite>
}

export interface Project {
	factories: Record<string, TestAgentFactory>
	basePath: string
	bosunApi?: BosunProjectApiV1
}

function parseBosunProjectApi(candidate: unknown): BosunProjectApiV1 | undefined {
	if (candidate == null) return undefined
	if (typeof candidate !== 'object' || Array.isArray(candidate)) {
		throw new Error('Invalid bosunApi export: expected an object')
	}

	const api = candidate as Partial<BosunProjectApiV1>
	if (api.version !== 1) {
		throw new Error('Invalid bosunApi export: expected version 1')
	}
	if (typeof api.getAgentMeta !== 'function') {
		throw new Error('Invalid bosunApi export: missing getAgentMeta(agentId)')
	}
	if (typeof api.resolveTestSuite !== 'function') {
		throw new Error('Invalid bosunApi export: missing resolveTestSuite(input)')
	}

	return api as BosunProjectApiV1
}

export async function getAgentFactories(agentsModule: string, importNonce?: number) {
	const baseUrl = pathToFileURL(agentsModule).href
	// IMPORTANT: The project's module graph (including `region-config.json`) is cached by the module loader.
	// When Bosun edits `region-config.json`, we bump an "import nonce" and re-import the project entrypoint
	// with a cache-busting query string so the updated JSON is picked up without restarting Bosun.
	const modUrl =
		typeof importNonce === 'number'
			? (() => {
					const u = new URL(baseUrl)
					u.searchParams.set('bosunImportNonce', String(importNonce))
					return u.href
				})()
			: baseUrl

	let mod: any
	try {
		mod = await import(modUrl)
	} catch (e) {
		console.error('Failed to import agents module:', modUrl, e)
	}

	const basePath = mod?.basePath ?? path.dirname(agentsModule)
	if (!mod?.basePath) {
		console.warn(`Agents module does not export basePath; falling back to ${basePath}.`)
	}

	if (!mod?.default) {
		throw new Error(`Cannot load agents from ${agentsModule}`)
	}

	return {
		basePath,
		factories: mod.default as Record<string, TestAgentFactory>,
		bosunApi: parseBosunProjectApi(mod?.bosunApi ?? mod?.default?.bosunApi)
	}
}
