import { z } from "@hono/zod-openapi";
import * as jmespath from "jmespath";

//#region src/utils/jmespath-utils.ts
const jmespathExt = jmespath;
/**
* Maximum allowed length for JMESPath expressions.
*/
const MAX_EXPRESSION_LENGTH = 1e3;
/**
* Validates a JMESPath expression by attempting to compile it.
* Uses the jmespath package which is already available in the codebase.
*
* @param expression - The JMESPath expression to validate
* @returns ValidationResult with valid flag and optional error message
*
* @example
* ```typescript
* const result = validateJMESPath('body.user.id');
* if (!result.valid) {
*   console.error(result.error);
* }
* ```
*/
function validateJMESPath(expression) {
	if (!expression || typeof expression !== "string") return {
		valid: false,
		error: "JMESPath expression must be a non-empty string"
	};
	try {
		jmespathExt.compile(expression);
		return { valid: true };
	} catch (error) {
		return {
			valid: false,
			error: `Invalid JMESPath expression: ${error instanceof Error ? error.message : String(error)}`
		};
	}
}
/**
* Validates a regex pattern by attempting to construct a RegExp object.
* Returns clear error messages for common regex issues.
*
* @param pattern - The regex pattern to validate (without delimiters)
* @returns ValidationResult with valid flag and optional error message
*
* @example
* ```typescript
* const result = validateRegex('v\\d+,(.+)');
* if (!result.valid) {
*   console.error(result.error);
* }
* ```
*/
function validateRegex(pattern) {
	if (pattern === null || pattern === void 0) return {
		valid: false,
		error: "Regex pattern must be provided"
	};
	if (typeof pattern !== "string") return {
		valid: false,
		error: "Regex pattern must be a string"
	};
	if (pattern === "") return { valid: true };
	try {
		new RegExp(pattern);
		return { valid: true };
	} catch (error) {
		return {
			valid: false,
			error: `Invalid regex pattern: ${error instanceof Error ? error.message : String(error)}`
		};
	}
}
/**
* Compiles a JMESPath expression.
* Wrapper around jmespath.compile() with proper typing.
*
* @param expression - The JMESPath expression to compile
* @returns The compiled expression object
* @throws Error if the expression is invalid
*/
function compileJMESPath(expression) {
	return jmespathExt.compile(expression);
}
/**
* Safely searches data using a JMESPath expression.
* Wrapper around jmespath.search() with proper typing.
*
* @param data - The object to search (e.g., template context, webhook body, tool result)
* @param expression - The JMESPath expression
* @returns The search result
*
* @example
* ```typescript
* const data = { users: [{ name: 'Alice' }] };
* const name = searchJMESPath<string>(data, 'users[0].name');
* // name is 'Alice'
*
* // Common use cases:
* // - Template contexts: { headers: {...}, body: {...} }
* // - Webhook payloads: { event: "...", data: {...} }
* // - Tool results: { status: "success", result: {...} }
* ```
*/
function searchJMESPath(data, expression) {
	return jmespath.search(data, expression);
}
/**
* Normalize a JMESPath expression by wrapping property names with dashes in quotes.
* JMESPath requires identifiers with special characters (like dashes) to be quoted.
*
* @param path - The JMESPath expression to normalize
* @returns The normalized JMESPath expression
*
* @example
* ```typescript
* normalizeJMESPath('headers.x-tenant-id');
* // Returns: 'headers."x-tenant-id"'
*
* normalizeJMESPath('api-responses[0].response-code');
* // Returns: '"api-responses"[0]."response-code"'
*
* normalizeJMESPath('simple.path');
* // Returns: 'simple.path' (unchanged)
* ```
*/
function normalizeJMESPath(path) {
	return path.split(".").map((segment) => {
		if (!segment.includes("-")) return segment;
		if (segment.startsWith("\"") && segment.includes("\"")) return segment;
		const bracketIndex = segment.indexOf("[");
		if (bracketIndex !== -1) return `"${segment.substring(0, bracketIndex)}"${segment.substring(bracketIndex)}`;
		return `"${segment}"`;
	}).join(".");
}
/**
* Dangerous patterns that should not appear in JMESPath expressions.
* These patterns are checked during secure validation to prevent injection attacks.
*/
const DANGEROUS_PATTERNS = [
	/\$\{.*\}/,
	/eval\s*\(/,
	/function\s*\(/,
	/constructor/,
	/prototype/,
	/__proto__/
];
/**
* Validates a JMESPath expression with security checks.
* Performs checks in order of cost: length (O(1)), patterns (O(n)), compile (expensive).
*
* @param expression - The JMESPath expression to validate
* @param options - Optional security options
* @returns ValidationResult with valid flag and optional error message
*
* @example
* ```typescript
* const result = validateJMESPathSecure('body.user.id');
* if (!result.valid) {
*   console.error(result.error);
* }
*
* // With custom options
* const result2 = validateJMESPathSecure('expression', { maxLength: 500 });
* ```
*/
function validateJMESPathSecure(expression, options) {
	if (!expression || typeof expression !== "string") return {
		valid: false,
		error: "JMESPath expression must be a non-empty string"
	};
	const maxLength = options?.maxLength ?? MAX_EXPRESSION_LENGTH;
	const patterns = options?.dangerousPatterns ?? DANGEROUS_PATTERNS;
	if (expression.length > maxLength) return {
		valid: false,
		error: `JMESPath expression exceeds maximum length of ${maxLength} characters`
	};
	for (const pattern of patterns) if (pattern.test(expression)) return {
		valid: false,
		error: `JMESPath expression contains dangerous pattern: ${pattern.source}`
	};
	try {
		jmespathExt.compile(expression);
		return { valid: true };
	} catch (error) {
		return {
			valid: false,
			error: `Invalid JMESPath expression: ${error instanceof Error ? error.message : String(error)}`
		};
	}
}
/**
* Creates a Zod string schema for JMESPath expressions with OpenAPI-visible constraints.
* Includes maxLength constraint and a description with valid/invalid examples.
*
* @param options - Optional configuration for the schema
* @returns A Zod string schema with maxLength and description
*
* @example
* ```typescript
* const schema = z.object({
*   transform: jmespathString().optional(),
* });
* ```
*/
function jmespathString(options) {
	const maxLen = options?.maxLength ?? MAX_EXPRESSION_LENGTH;
	return z.string().max(maxLen).describe(`JMESPath expression (max ${maxLen} chars). Valid: "data.items[0].name", "results[?status=='active']", "keys(@)". Invalid: "\${...}" (template injection), "eval" calls, "constructor", "__proto__".`);
}

//#endregion
export { DANGEROUS_PATTERNS, MAX_EXPRESSION_LENGTH, compileJMESPath, jmespathString, normalizeJMESPath, searchJMESPath, validateJMESPath, validateJMESPathSecure, validateRegex };