<template>
	<footer class="composer-panel" @dragover.prevent="onDragOver" @dragleave="onDragLeave" @drop.prevent="onDrop">
		<!-- 工具确认模式：替换整个输入区域 -->
		<div v-if="pendingToolConfirm" class="composer-box tool-confirm-box">
			<div class="tool-confirm-info">
				<span class="tool-confirm-icon">&#9888;</span>
				<span class="tool-confirm-label">{{ pendingToolConfirm.toolLabel }}</span>
				<code class="tool-confirm-command">{{ formatConfirmCommand(pendingToolConfirm.args) }}</code>
			</div>
			<div class="tool-confirm-reason">{{ pendingToolConfirm.riskReason }}</div>
			<div class="tool-confirm-actions">
				<button class="secondary-btn tool-confirm-reject" @click="handleReject">拒绝</button>
				<button class="primary-btn tool-confirm-allow" @click="handleAllow">允许执行</button>
			</div>
		</div>

		<!-- 正常输入模式 -->
		<template v-else>
			<chat-attachment-preview :attachments="attachments" @remove="removeAttachment" />
			<div class="composer-box" :class="{ 'composer-box--dragover': isDragOver }">
				<chat-attachment-button @select="handleFilesSelected" />
				<el-input
					:model-value="modelValue"
					type="textarea"
					:autosize="{ minRows: 2, maxRows: 6 }"
					placeholder="输入消息"
					:disabled="!canSend"
					@update:model-value="value => emit('update:modelValue', String(value))"
					@keydown="onKeyDown"
					@paste="onPaste"
				/>
				<div class="composer-box__actions">
					<button class="secondary-btn" @click="emit('new-session')">新会话</button>
					<button
						class="primary-btn"
						:disabled="!canSend || (!modelValue.trim() && !attachments.length)"
						@click="handleSendClick"
					>
						{{ loading ? '处理中...' : '发送' }}
					</button>
				</div>
			</div>
		</template>
	</footer>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import { useCool } from '/@/cool';
import type { ChatAttachment } from '../../types/index';
import ChatAttachmentButton from './ChatAttachmentButton.vue';
import ChatAttachmentPreview from './ChatAttachmentPreview.vue';
import type { AttachmentItem } from './ChatAttachmentPreview.vue';

const props = defineProps<{
	modelValue: string;
	canSend: boolean;
	loading: boolean;
	pendingToolConfirm?: {
		requestId: string;
		toolName: string;
		toolLabel: string;
		args: Record<string, unknown>;
		riskReason: string;
	} | null;
}>();

const emit = defineEmits<{
	'update:modelValue': [value: string];
	'new-session': [];
	send: [attachments?: ChatAttachment[]];
	keydown: [event: KeyboardEvent];
	'tool-confirm': [requestId: string, confirmed: boolean];
}>();

const { service } = useCool();
const attachments = ref<AttachmentItem[]>([]);
const isDragOver = ref(false);
function getFileType(mime: string): ChatAttachment['type'] {
	if (mime.startsWith('image/')) return 'image';
	if (mime.startsWith('video/')) return 'video';
	if (mime === 'application/pdf') return 'pdf';
	if (mime.includes('word') || mime.includes('excel') || mime.includes('spreadsheet') || mime.includes('document')) return 'document';
	return 'other';
}

async function uploadFile(item: AttachmentItem) {
	const file = (item as any)._file as File;
	if (!file) return;
	const formData = new FormData();
	formData.append('file', file);
	try {
		const res = await service.request({ url: '/admin/base/comm/upload', method: 'POST', data: formData });
		const idx = attachments.value.findIndex(a => a.id === item.id);
		if (idx !== -1) {
			attachments.value[idx].url = res;
			attachments.value[idx].progress = 100;
		}
	} catch {
		attachments.value = attachments.value.filter(a => a.id !== item.id);
	}
}

function addFiles(files: File[]) {
	for (const file of files) {
		const id = crypto.randomUUID();
		const type = getFileType(file.type);
		const item: AttachmentItem & { _file?: File } = {
			id,
			type,
			name: file.name,
			size: file.size,
			mimeType: file.type,
			progress: 0,
		};
		if (type === 'image') {
			item.previewUrl = URL.createObjectURL(file);
		}
		(item as any)._file = file;
		attachments.value.push(item);
		uploadFile(item);
	}
}

function handleFilesSelected(files: File[]) {
	addFiles(files);
}

function removeAttachment(id: string) {
	const item = attachments.value.find(a => a.id === id);
	if (item?.previewUrl) URL.revokeObjectURL(item.previewUrl);
	attachments.value = attachments.value.filter(a => a.id !== id);
}

function handleSendClick() {
	const ready = attachments.value.filter(a => a.url);
	if (ready.length) {
		const payload: ChatAttachment[] = ready.map(a => ({
			id: a.id,
			type: a.type,
			url: a.url!,
			name: a.name,
			size: a.size,
			mimeType: a.mimeType,
		}));
		attachments.value = [];
		emit('send', payload);
	} else {
		emit('send');
	}
}

function onDragOver() {
	isDragOver.value = true;
}
function onDragLeave() {
	isDragOver.value = false;
}
function onDrop(e: DragEvent) {
	isDragOver.value = false;
	const files = e.dataTransfer?.files;
	if (files?.length) addFiles(Array.from(files));
}
function onPaste(e: ClipboardEvent) {
	const files = e.clipboardData?.files;
	if (files?.length) {
		e.preventDefault();
		addFiles(Array.from(files));
	}
}

function onKeyDown(event: KeyboardEvent) {
	if (event.key === 'Enter' && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
		event.preventDefault();
		handleSendClick();
		return;
	}
	emit('keydown', event);
}

function formatConfirmCommand(args: Record<string, unknown>): string {
	if (typeof args.command === 'string') return args.command;
	return JSON.stringify(args);
}

function handleAllow() {
	if (props.pendingToolConfirm?.requestId) {
		emit('tool-confirm', props.pendingToolConfirm.requestId, true);
	}
}

function handleReject() {
	if (props.pendingToolConfirm?.requestId) {
		emit('tool-confirm', props.pendingToolConfirm.requestId, false);
	}
}
</script>

<style scoped>
.tool-confirm-box {
	display: flex;
	flex-direction: column;
	gap: 12px;
	padding: 16px;
	border: 1px solid var(--el-color-warning-light-5, #f5dab1);
	border-radius: 8px;
	background: linear-gradient(180deg, rgba(230, 162, 60, 0.06), rgba(230, 162, 60, 0.02));
	animation: tool-confirm-enter 0.25s ease-out;
}

@keyframes tool-confirm-enter {
	from {
		opacity: 0;
		transform: translateY(8px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

.tool-confirm-info {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
}

.tool-confirm-icon {
	color: var(--el-color-warning, #e6a23c);
	font-size: 18px;
	font-weight: bold;
}

.tool-confirm-label {
	font-weight: 600;
	color: var(--el-text-color-primary, #303133);
}

.tool-confirm-command {
	flex: 1;
	min-width: 0;
	padding: 4px 8px;
	background: var(--el-fill-color-light, #f5f7fa);
	border-radius: 4px;
	font-family: 'Menlo', 'Monaco', 'Consolas', monospace;
	font-size: 13px;
	color: var(--el-text-color-regular, #606266);
	word-break: break-all;
	overflow-wrap: break-word;
}

.tool-confirm-reason {
	font-size: 13px;
	color: var(--el-color-warning, #e6a23c);
}

.tool-confirm-actions {
	display: flex;
	justify-content: flex-end;
	gap: 8px;
}

.tool-confirm-reject {
	color: var(--el-color-danger, #f56c6c);
	border-color: var(--el-color-danger-light-5, #fbc4c4);
}

.tool-confirm-allow {
	background: var(--el-color-success, #67c23a);
	border-color: var(--el-color-success, #67c23a);
}
</style>
