import type { ParsedFilter } from './templateFilters.js';

export interface ParsedSegmentPart {
	type: 'path' | 'literal';
	value: string;
	filters: ParsedFilter[];
}

export interface ParsedSegment {
	parts: ParsedSegmentPart[];
}

export function parseSegment(raw: string): ParsedSegment {
	const trimmed = raw.trim();
	const parts: ParsedSegmentPart[] = [];
	const tokens = splitOnPlus(trimmed);

	for (const token of tokens) {
		const t = token.trim();
		if (
			(t.startsWith("'") && t.endsWith("'")) ||
			(t.startsWith('"') && t.endsWith('"'))
		) {
			parts.push({ type: 'literal', value: t.slice(1, -1), filters: [] });
		} else {
			const colonParts = splitOnColons(t);
			const path = colonParts[0];
			const filters = colonParts.slice(1).map(parseFilterToken);
			parts.push({ type: 'path', value: path, filters });
		}
	}

	return { parts };
}

function parseFilterToken(token: string): ParsedFilter {
	const parenIndex = token.indexOf('(');
	if (parenIndex === -1) {
		return { name: token, args: [] };
	}
	const name = token.slice(0, parenIndex);
	const argsStr = token.slice(parenIndex + 1, -1); // strip parens
	const args = splitArgs(argsStr).map(parseArg);
	return { name, args };
}

function parseArg(raw: string): string | number {
	const trimmed = raw.trim();
	if (
		(trimmed.startsWith("'") && trimmed.endsWith("'")) ||
		(trimmed.startsWith('"') && trimmed.endsWith('"'))
	) {
		return trimmed.slice(1, -1);
	}
	const num = Number(trimmed);
	return isNaN(num) ? trimmed : num;
}

/** Split on `+` outside of quotes and parentheses */
function splitOnPlus(str: string): string[] {
	return splitOutside(str, '+');
}

/** Split on `:` outside of quotes and parentheses */
function splitOnColons(str: string): string[] {
	return splitOutside(str, ':');
}

/** Split on `,` outside of quotes and parentheses */
function splitArgs(str: string): string[] {
	return splitOutside(str, ',');
}

function splitOutside(str: string, delimiter: string): string[] {
	const results: string[] = [];
	let current = '';
	let inQuote: string | false = false;
	let parenDepth = 0;

	for (let i = 0; i < str.length; i++) {
		const ch = str[i];

		if ((ch === "'" || ch === '"') && parenDepth === 0 && !inQuote) {
			inQuote = ch;
			current += ch;
		} else if (inQuote && ch === inQuote) {
			inQuote = false;
			current += ch;
		} else if (inQuote) {
			current += ch;
		} else if (ch === '(') {
			parenDepth++;
			current += ch;
		} else if (ch === ')') {
			parenDepth--;
			current += ch;
		} else if (ch === delimiter && parenDepth === 0) {
			results.push(current);
			current = '';
		} else {
			current += ch;
		}
	}

	if (current) results.push(current);
	return results;
}
