import { t } from '/@/plugins/i18n';

export interface ToolRenderSource {
	toolCallId: string;
	toolName: string;
	label?: string;
	args?: Record<string, unknown>;
	result?: string;
	rawResult?: {
		type: 'text' | 'json' | 'image' | 'images';
		text?: string;
		data?: unknown;
		url?: string;
		mimeType?: string;
		width?: number;
		height?: number;
		bytes?: number;
		originalWidth?: number;
		originalHeight?: number;
		originalBytes?: number;
		resized?: boolean;
		images?: {
			url: string;
			mimeType?: string;
			label?: string;
			purpose?: string;
			reason?: string;
			damageId?: string;
			timestamp?: number;
			width?: number;
			height?: number;
			seed?: number;
		}[];
	};
	status: 'running' | 'done' | 'error';
}

export interface ToolRenderProjection extends ToolRenderSource {
	key: string;
	label: string;
	statusLabel: string;
	isLongResult: boolean;
	showArgs: boolean;
	metaItems: ToolRenderMetaItem[];
}

type ToolRenderer = (tool: ToolRenderSource) => ToolRenderProjection;

export interface ToolRendererCapability {
	custom: boolean;
	streaming: boolean;
	metaKinds: ToolRenderMetaItem['kind'][];
	showsArgs: 'never' | 'running' | 'always';
	collapsibleResult: boolean;
	description: string;
}

export interface ToolRenderMetaItem {
	label: string;
	value: string;
	kind?: 'path' | 'offset' | 'log' | 'count' | 'mode';
}

const defaultRenderer: ToolRenderer = tool => {
	const result = typeof tool.result === 'string' ? tool.result : '';
	return {
		...tool,
		key: tool.toolCallId,
		label: tool.label || tool.toolName || 'Tool',
		statusLabel: tool.status === 'running' ? t('运行中') : tool.status === 'done' ? t('完成') : t('失败'),
		isLongResult: result.length > 280 || result.split('\n').length > 6,
		showArgs: Boolean(tool.args) && tool.status === 'running',
		metaItems: [],
	};
};

const registry = new Map<string, ToolRenderer>();
const capabilityRegistry = new Map<string, Omit<ToolRendererCapability, 'custom'>>();

registry.set('bash', tool => {
	const projection = defaultRenderer(tool);
	const commandMeta: ToolRenderMetaItem[] = [];
	if (tool.args?.command) {
		commandMeta.push({ label: '$', value: String(tool.args.command), kind: 'path' });
	}
	return {
		...projection,
		label: tool.label || 'Bash',
		showArgs: true,
		metaItems: [...commandMeta, ...extractArgMeta(tool.args, ['cwd']), ...extractFullOutputMeta(tool.result)],
	};
});
capabilityRegistry.set('bash', {
	streaming: true,
	metaKinds: ['path', 'log'],
	showsArgs: 'running',
	collapsibleResult: true,
	description: t('识别工作目录与完整日志路径'),
});

registry.set('edit', tool => {
	const projection = defaultRenderer(tool);
	return {
		...projection,
		label: tool.label || t('精确编辑'),
		showArgs: Boolean(tool.args),
		isLongResult: true,
		metaItems: extractArgMeta(tool.args, ['path']),
	};
});
capabilityRegistry.set('edit', {
	streaming: true,
	metaKinds: ['path'],
	showsArgs: 'always',
	collapsibleResult: true,
	description: t('展示编辑参数与目标文件路径'),
});

registry.set('patch', tool => {
	const projection = defaultRenderer(tool);
	return {
		...projection,
		label: tool.label || t('模糊补丁'),
		showArgs: Boolean(tool.args),
		isLongResult: true,
		metaItems: [...extractArgMeta(tool.args, ['path']), ...extractPatchMeta(tool.result)],
	};
});
capabilityRegistry.set('patch', {
	streaming: true,
	metaKinds: ['path', 'offset', 'mode'],
	showsArgs: 'always',
	collapsibleResult: true,
	description: t('展示补丁参数、匹配策略与首个变更行'),
});

registry.set('write_file', tool => {
	const projection = defaultRenderer(tool);
	return {
		...projection,
		label: tool.label || t('写入文件'),
		showArgs: Boolean(tool.args) && tool.status === 'running',
		metaItems: extractArgMeta(tool.args, ['path']),
	};
});
capabilityRegistry.set('write_file', {
	streaming: true,
	metaKinds: ['path'],
	showsArgs: 'running',
	collapsibleResult: false,
	description: t('展示写入目标文件路径'),
});

registry.set('read_file', tool => {
	const projection = defaultRenderer(tool);
	return {
		...projection,
		label: tool.label || t('读取文件'),
		metaItems: [...extractArgMeta(tool.args, ['path', 'offset', 'limit']), ...extractContinuationMeta(tool.result)],
	};
});
capabilityRegistry.set('read_file', {
	streaming: true,
	metaKinds: ['path', 'offset'],
	showsArgs: 'running',
	collapsibleResult: true,
	description: t('识别文件路径、分页参数与继续读取 offset'),
});

registry.set('list_dir', tool => {
	const projection = defaultRenderer(tool);
	return {
		...projection,
		label: tool.label || t('列出目录'),
		metaItems: [...extractArgMeta(tool.args, ['path', 'limit']), ...extractDirectorySummaryMeta(tool.result)],
	};
});
capabilityRegistry.set('list_dir', {
	streaming: true,
	metaKinds: ['path', 'count', 'mode'],
	showsArgs: 'running',
	collapsibleResult: false,
	description: t('展示目录路径、结果上限与截断提示'),
});

registry.set('find_files', tool => {
	const projection = defaultRenderer(tool);
	return {
		...projection,
		label: tool.label || t('查找文件'),
		showArgs: Boolean(tool.args) && tool.status === 'running',
		metaItems: [...extractArgMeta(tool.args, ['path', 'pattern', 'limit']), ...extractResultNoticeMeta(tool.result, 'find_files')],
	};
});
capabilityRegistry.set('find_files', {
	streaming: true,
	metaKinds: ['path', 'mode', 'count'],
	showsArgs: 'running',
	collapsibleResult: false,
	description: t('展示搜索根目录、模式与结果上限'),
});

registry.set('grep', tool => {
	const projection = defaultRenderer(tool);
	return {
		...projection,
		label: tool.label || t('搜索内容'),
		showArgs: Boolean(tool.args) && tool.status === 'running',
		isLongResult: true,
		metaItems: [
			...extractArgMeta(tool.args, ['path', 'pattern', 'glob', 'context', 'limit']),
			...extractResultNoticeMeta(tool.result, 'grep'),
		],
	};
});
capabilityRegistry.set('grep', {
	streaming: true,
	metaKinds: ['path', 'mode', 'offset', 'count'],
	showsArgs: 'running',
	collapsibleResult: true,
	description: t('展示搜索目录、内容模式、Glob 与结果上限'),
});

registry.set('todo', tool => {
	const projection = defaultRenderer(tool);
	return {
		...projection,
		label: tool.label || '任务规划',
		showArgs: false,
		isLongResult: true,
	};
});
capabilityRegistry.set('todo', {
	streaming: true,
	metaKinds: [],
	showsArgs: 'never',
	collapsibleResult: true,
	description: t('任务规划工具，展示待办事项列表'),
});

function extractArgMeta(args: Record<string, unknown> | undefined, keys: string[]): ToolRenderMetaItem[] {
	if (!args) return [];
	return keys
		.map(key => {
			const value = args[key];
			if (value === undefined || value === null || value === '') return null;
			return {
				label: argLabel(key),
				value: String(value),
				kind: argKind(key),
			} as ToolRenderMetaItem;
		})
		.filter(Boolean) as ToolRenderMetaItem[];
}

function extractFullOutputMeta(result: string | undefined): ToolRenderMetaItem[] {
	if (!result) return [];
	const match = result.match(/完整输出[:：]\s*([^\]\n]+)/);
	if (!match) return [];
	return [{ label: t('完整日志'), value: match[1].trim(), kind: 'log' }];
}

function extractContinuationMeta(result: string | undefined): ToolRenderMetaItem[] {
	if (!result) return [];
	const match = result.match(/继续读取[:：]\s*offset=(\d+)/);
	if (!match) return [];
	return [{ label: t('继续读取'), value: `offset=${match[1]}`, kind: 'offset' }];
}

function extractDirectorySummaryMeta(result: string | undefined): ToolRenderMetaItem[] {
	if (!result) return [];
	const items: ToolRenderMetaItem[] = [];
	if (result.includes('limit=')) {
		items.push({ label: t('目录截断'), value: t('已命中条目上限'), kind: 'count' });
	}
	if (result.includes('输出大小已达到')) {
		items.push({ label: t('输出截断'), value: t('已命中大小上限'), kind: 'mode' });
	}
	return items;
}

function extractPatchMeta(result: string | undefined): ToolRenderMetaItem[] {
	if (!result) return [];
	const items: ToolRenderMetaItem[] = [];
	const firstChangedLine = result.match(/首个变更行[:：]\s*(\d+)/);
	if (firstChangedLine) {
		items.push({ label: t('首个变更行'), value: firstChangedLine[1], kind: 'offset' });
	}
	const strategy = result.match(/匹配策略[:：]\s*([^\n]+)/);
	if (strategy) {
		items.push({ label: t('匹配策略'), value: strategy[1].trim(), kind: 'mode' });
	}
	return items;
}

function extractResultNoticeMeta(result: string | undefined, kind: 'find_files' | 'grep'): ToolRenderMetaItem[] {
	if (!result) return [];
	const items: ToolRenderMetaItem[] = [];
	if (result.includes('limit=')) {
		items.push({ label: t('结果上限'), value: t('已命中数量上限'), kind: 'count' });
	}
	if (result.includes('输出大小已达到')) {
		items.push({ label: t('输出截断'), value: t('已命中大小上限'), kind: 'mode' });
	}
	if (kind === 'grep' && result.includes('部分长行已截断')) {
		items.push({ label: t('长行提示'), value: t('部分长行已截断'), kind: 'mode' });
	}
	return items;
}

function argLabel(key: string): string {
	if (key === 'path') return t('路径');
	if (key === 'cwd') return t('工作目录');
	if (key === 'offset') return t('起始行');
	if (key === 'limit') return t('限制');
	if (key === 'context') return t('上下文');
	if (key === 'pattern') return t('模式');
	if (key === 'glob') return t('Glob');
	return key;
}

function argKind(key: string): ToolRenderMetaItem['kind'] {
	if (key === 'path' || key === 'cwd') return 'path';
	if (key === 'offset' || key === 'limit' || key === 'context') return 'offset';
	if (key === 'pattern' || key === 'glob') return 'mode';
	return undefined;
}

export function registerToolRenderer(name: string, renderer: ToolRenderer) {
	registry.set(name, renderer);
}

export function getToolRenderer(name: string): ToolRenderer {
	return registry.get(name) || defaultRenderer;
}

export function projectToolRender(tool: ToolRenderSource): ToolRenderProjection {
	return getToolRenderer(tool.toolName)(tool);
}

export function hasCustomToolRenderer(name: string): boolean {
	return registry.has(name);
}

export function listRegisteredToolRenderers(): string[] {
	return [...registry.keys()].sort();
}

export function getToolRendererCapability(name: string): ToolRendererCapability {
	const capability = capabilityRegistry.get(name);
	if (!capability) {
		return {
			custom: false,
			streaming: false,
			metaKinds: [],
			showsArgs: 'running',
			collapsibleResult: true,
			description: t('默认文本结果展示'),
		};
	}
	return {
		custom: registry.has(name),
		...capability,
	};
}
