import { getLogger } from "../../../logger.js";
import { executionLimitsDefaults } from "../constants/execution-limits/defaults.js";
import { COMPRESSION_HARD_LIMIT, COMPRESSION_SAFETY_BUFFER } from "../constants/execution-limits/index.js";
import { ModelInfoMap } from "llm-info";

//#region src/domains/run/utils/model-context-utils.ts
const logger = getLogger("ModelContextUtils");
function extractModelIdForLlmInfo(modelInput) {
	let modelString;
	if (typeof modelInput === "string") {
		modelString = modelInput.trim();
		if (!modelString) return null;
	} else if (modelInput?.model) {
		modelString = modelInput.model.trim();
		if (!modelString) return null;
	} else return null;
	let modelId;
	if (modelString.includes("/")) {
		const parts = modelString.split("/");
		modelId = parts[parts.length - 1];
	} else modelId = modelString;
	if (modelId in ModelInfoMap) return modelId;
	const matchingModels = Object.keys(ModelInfoMap).filter((key) => key.startsWith(modelId));
	if (matchingModels.length > 0) return matchingModels.sort().reverse()[0];
	return modelId;
}
/**
* Get context window size for a model using llm-info
* Falls back to default values if model not found
*/
function getModelContextWindow(modelSettings) {
	const defaultContextWindow = 12e4;
	if (modelSettings?.providerOptions?.contextWindowSize && typeof modelSettings.providerOptions.contextWindowSize === "number" && modelSettings.providerOptions.contextWindowSize > 0) {
		const contextWindowSize = modelSettings.providerOptions.contextWindowSize;
		logger.debug({
			contextWindow: contextWindowSize,
			model: modelSettings.model
		}, "Using context window from providerOptions");
		return {
			contextWindow: contextWindowSize,
			hasValidContextWindow: true,
			modelId: modelSettings.model || "custom",
			source: "provider-options"
		};
	}
	if (!modelSettings?.model) {
		logger.debug({}, "No model settings provided, using fallback");
		return {
			contextWindow: defaultContextWindow,
			hasValidContextWindow: false,
			modelId: "unknown",
			source: "fallback"
		};
	}
	const modelId = extractModelIdForLlmInfo(modelSettings);
	if (!modelId) {
		logger.debug({ modelString: modelSettings.model }, "Could not extract model ID for llm-info lookup");
		return {
			contextWindow: defaultContextWindow,
			hasValidContextWindow: false,
			modelId: modelSettings.model,
			source: "fallback"
		};
	}
	try {
		const modelDetails = ModelInfoMap[modelId];
		if (modelDetails?.contextWindowTokenLimit && modelDetails.contextWindowTokenLimit > 0) {
			logger.debug({
				modelId,
				contextWindow: modelDetails.contextWindowTokenLimit,
				originalModel: modelSettings.model
			}, "Found context window from llm-info");
			return {
				contextWindow: modelDetails.contextWindowTokenLimit,
				hasValidContextWindow: true,
				modelId,
				source: "llm-info"
			};
		}
		logger.debug({
			modelId,
			modelDetails,
			originalModel: modelSettings.model
		}, "No valid context window found in llm-info");
	} catch (error) {
		logger.debug({
			modelId,
			error: error instanceof Error ? error.message : String(error),
			originalModel: modelSettings.model
		}, "Error getting model details from llm-info");
	}
	logger.debug({
		modelId,
		defaultContextWindow
	}, "Using fallback context window");
	return {
		contextWindow: defaultContextWindow,
		hasValidContextWindow: false,
		modelId,
		source: "fallback"
	};
}
/**
* Get model-size aware compression parameters
* Uses aggressive thresholds for better utilization, especially on large models
*/
function getCompressionParams(contextWindow) {
	if (contextWindow < 1e5) return {
		threshold: .85,
		bufferPct: .1
	};
	if (contextWindow < 5e5) return {
		threshold: .9,
		bufferPct: .07
	};
	return {
		threshold: .95,
		bufferPct: .04
	};
}
/**
* Get compression configuration based on model context window
* Uses actual model context window when available, otherwise falls back to environment variables
* @param modelSettings - Model settings to get context window for
* @param targetPercentage - Target percentage of context window to use (e.g., 0.5 for conversation, undefined for model-aware defaults)
*/
function getCompressionConfigForModel(modelSettings, targetPercentage) {
	const modelContextInfo = getModelContextWindow(modelSettings);
	const envHardLimit = parseInt(process.env.AGENTS_COMPRESSION_HARD_LIMIT || COMPRESSION_HARD_LIMIT.toString(), 10);
	const envSafetyBuffer = parseInt(process.env.AGENTS_COMPRESSION_SAFETY_BUFFER || COMPRESSION_SAFETY_BUFFER.toString(), 10);
	const envEnabledValue = process.env.AGENTS_COMPRESSION_ENABLED;
	const enabled = envEnabledValue !== void 0 ? envEnabledValue !== "false" : executionLimitsDefaults.COMPRESSION_ENABLED;
	if (modelContextInfo.hasValidContextWindow && modelContextInfo.contextWindow) {
		let hardLimit;
		let safetyBuffer;
		let logContext;
		if (targetPercentage !== void 0) {
			hardLimit = Math.floor(modelContextInfo.contextWindow * targetPercentage);
			safetyBuffer = Math.floor(modelContextInfo.contextWindow * .05);
			const triggerPoint = hardLimit - safetyBuffer;
			const triggerPercentage = (triggerPoint / modelContextInfo.contextWindow * 100).toFixed(1);
			logContext = {
				modelId: modelContextInfo.modelId,
				contextWindow: modelContextInfo.contextWindow,
				hardLimit,
				safetyBuffer,
				triggerPoint,
				triggerPercentage: `${triggerPercentage}%`,
				targetPercentage: `${(targetPercentage * 100).toFixed(1)}%`,
				compressionType: targetPercentage <= .6 ? "conversation" : "mid-generation"
			};
			logger.info(logContext, "Using percentage-based compression configuration");
		} else {
			const params = getCompressionParams(modelContextInfo.contextWindow);
			hardLimit = Math.floor(modelContextInfo.contextWindow * params.threshold);
			safetyBuffer = Math.floor(modelContextInfo.contextWindow * params.bufferPct);
			const triggerPoint = hardLimit - safetyBuffer;
			const triggerPercentage = (triggerPoint / modelContextInfo.contextWindow * 100).toFixed(1);
			logContext = {
				modelId: modelContextInfo.modelId,
				contextWindow: modelContextInfo.contextWindow,
				hardLimit,
				safetyBuffer,
				triggerPoint,
				triggerPercentage: `${triggerPercentage}%`,
				threshold: params.threshold,
				bufferPct: params.bufferPct
			};
			logger.info(logContext, "Using model-size aware compression configuration");
		}
		return {
			hardLimit,
			safetyBuffer,
			enabled,
			source: "model-specific",
			modelContextInfo
		};
	}
	const source = process.env.AGENTS_COMPRESSION_HARD_LIMIT ? "environment" : "default";
	logger.debug({
		modelId: modelContextInfo.modelId,
		hardLimit: envHardLimit,
		safetyBuffer: envSafetyBuffer,
		source
	}, "Using fallback compression configuration");
	return {
		hardLimit: envHardLimit,
		safetyBuffer: envSafetyBuffer,
		enabled,
		source,
		modelContextInfo
	};
}

//#endregion
export { extractModelIdForLlmInfo, getCompressionConfigForModel, getModelContextWindow };