import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { getFeynmanHome } from "../config/paths.js";

export type PiWebSearchProvider = "auto" | "perplexity" | "exa" | "gemini";

export type PiWebAccessConfig = Record<string, unknown> & {
	route?: PiWebSearchProvider;
	provider?: PiWebSearchProvider;
	searchProvider?: PiWebSearchProvider;
	perplexityApiKey?: string;
	exaApiKey?: string;
	geminiApiKey?: string;
	chromeProfile?: string;
};

export type PiWebAccessStatus = {
	configPath: string;
	searchProvider: PiWebSearchProvider;
	requestProvider: PiWebSearchProvider;
	perplexityConfigured: boolean;
	exaConfigured: boolean;
	geminiApiConfigured: boolean;
	chromeProfile?: string;
	routeLabel: string;
	note: string;
};

export function getPiWebSearchConfigPath(home?: string): string {
	const feynmanHome = home ? resolve(home, ".feynman") : getFeynmanHome();
	return resolve(feynmanHome, "web-search.json");
}

function normalizeProvider(value: unknown): PiWebSearchProvider | undefined {
	return value === "auto" || value === "perplexity" || value === "exa" || value === "gemini" ? value : undefined;
}

function normalizeNonEmptyString(value: unknown): string | undefined {
	return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
}

export function loadPiWebAccessConfig(configPath = getPiWebSearchConfigPath()): PiWebAccessConfig {
	if (!existsSync(configPath)) {
		return {};
	}

	try {
		const parsed = JSON.parse(readFileSync(configPath, "utf8")) as PiWebAccessConfig;
		return parsed && typeof parsed === "object" ? parsed : {};
	} catch {
		return {};
	}
}

export function savePiWebAccessConfig(
	updates: Partial<Record<keyof PiWebAccessConfig, unknown>>,
	configPath = getPiWebSearchConfigPath(),
): void {
	const merged: Record<string, unknown> = { ...loadPiWebAccessConfig(configPath) };
	for (const [key, value] of Object.entries(updates)) {
		if (value === undefined) {
			delete merged[key];
		} else {
			merged[key] = value;
		}
	}

	mkdirSync(dirname(configPath), { recursive: true });
	writeFileSync(configPath, JSON.stringify(merged, null, 2) + "\n", "utf8");
}

function formatRouteLabel(provider: PiWebSearchProvider): string {
	switch (provider) {
		case "perplexity":
			return "Perplexity";
		case "exa":
			return "Exa";
		case "gemini":
			return "Gemini";
		default:
			return "Auto";
	}
}

function formatRouteNote(provider: PiWebSearchProvider): string {
	switch (provider) {
		case "perplexity":
			return "Pi web-access will use Perplexity for search.";
		case "exa":
			return "Pi web-access will use Exa for search.";
		case "gemini":
			return "Pi web-access will use Gemini API or Gemini Browser.";
		default:
			return "Pi web-access will try Perplexity, then Exa, then Gemini API, then Gemini Browser.";
	}
}

export function getPiWebAccessStatus(
	config: PiWebAccessConfig = loadPiWebAccessConfig(),
	configPath = getPiWebSearchConfigPath(),
): PiWebAccessStatus {
	const searchProvider =
		normalizeProvider(config.searchProvider) ?? normalizeProvider(config.route) ?? normalizeProvider(config.provider) ?? "auto";
	const requestProvider = normalizeProvider(config.provider) ?? normalizeProvider(config.route) ?? searchProvider;
	const perplexityConfigured = Boolean(normalizeNonEmptyString(config.perplexityApiKey));
	const exaConfigured = Boolean(normalizeNonEmptyString(config.exaApiKey));
	const geminiApiConfigured = Boolean(normalizeNonEmptyString(config.geminiApiKey));
	const chromeProfile = normalizeNonEmptyString(config.chromeProfile);
	const effectiveProvider = searchProvider;

	return {
		configPath,
		searchProvider,
		requestProvider,
		perplexityConfigured,
		exaConfigured,
		geminiApiConfigured,
		chromeProfile,
		routeLabel: formatRouteLabel(effectiveProvider),
		note: formatRouteNote(effectiveProvider),
	};
}

export function formatPiWebAccessDoctorLines(
	status: PiWebAccessStatus = getPiWebAccessStatus(),
): string[] {
	return [
		"web access: pi-web-access",
		`  search route: ${status.routeLabel}`,
		`  request route: ${status.requestProvider}`,
		`  perplexity api: ${status.perplexityConfigured ? "configured" : "not configured"}`,
		`  exa api: ${status.exaConfigured ? "configured" : "not configured"}`,
		`  gemini api: ${status.geminiApiConfigured ? "configured" : "not configured"}`,
		`  browser profile: ${status.chromeProfile ?? "default Chromium profile"}`,
		`  config path: ${status.configPath}`,
		`  note: ${status.note}`,
	];
}
