<template>
	<el-dialog
		v-model="visible"
		title="存储服务管理"
		width="1100px"
		top="6vh"
		destroy-on-close
		:close-on-click-modal="false"
	>
		<div class="storage-modal" v-loading="pageLoading">
			<el-alert
				title="选择引擎查看配置，支持修改保存和连通测试。"
				type="info"
				:closable="false"
				show-icon
			/>

			<div class="storage-actions">
				<el-button type="primary" :loading="initLoading" @click="handleInit">
					初始化存储
				</el-button>
				<el-button :loading="engineLoading" @click="loadEngines">刷新列表</el-button>
			</div>

			<div class="storage-layout">
				<aside class="engine-list">
					<div class="engine-list__header">引擎列表</div>
					<div v-if="engines.length" class="engine-list__body">
						<div
							v-for="item in engines"
							:key="item.name"
							class="engine-card"
							:class="{ 'engine-card--active': selectedProvider === item.name }"
							@click="selectProvider(item.name)"
						>
							<div class="engine-card__top">
								<div class="engine-card__name">{{ formatProviderLabel(item.name) }}</div>
							</div>
							<div class="engine-card__meta">
								<el-tag size="small" :type="item.allowed ? 'success' : 'info'" effect="plain">
									{{ item.allowed ? '允许' : '不允许' }}
								</el-tag>
								<el-tag size="small" :type="item.available ? 'primary' : 'warning'" effect="plain">
									{{ item.available ? '可用' : '不可用' }}
								</el-tag>
							</div>
							<div class="engine-card__desc">
								{{ item.description || '点击加载配置信息' }}
							</div>
						</div>
					</div>
					<el-empty v-else description="暂无引擎" />
				</aside>

				<section class="config-panel">
					<template v-if="selectedProvider">
						<div class="config-panel__header">
							<div>
								<div class="config-panel__title">
									{{ formatProviderLabel(selectedProvider) }} 配置
								</div>
								<div class="config-panel__desc">点击左侧引擎后加载配置信息，修改后保存。</div>
							</div>
						</div>

						<el-form :model="form" label-position="top">
							<template v-if="selectedProvider === 'local'">
								<el-form-item label="存储前缀">
									<el-input v-model="form.local.path_prefix" placeholder="例如 knowledge/files" />
								</el-form-item>
							</template>

							<template v-else-if="selectedProvider === 'minio'">
								<div class="form-grid">
									<el-form-item label="Endpoint">
										<el-input v-model="form.minio.endpoint" placeholder="127.0.0.1:9000" />
									</el-form-item>
									<el-form-item label="Mode">
										<el-input v-model="form.minio.mode" placeholder="docker" />
									</el-form-item>
									<el-form-item label="Access Key ID">
										<el-input v-model="form.minio.access_key_id" />
									</el-form-item>
									<el-form-item label="Secret Access Key">
										<el-input v-model="form.minio.secret_access_key" show-password />
									</el-form-item>
									<el-form-item label="Bucket">
										<el-input v-model="form.minio.bucket_name" />
									</el-form-item>
									<el-form-item label="Path Prefix">
										<el-input v-model="form.minio.path_prefix" />
									</el-form-item>
								</div>
								<el-form-item label="Use SSL">
									<el-switch v-model="form.minio.use_ssl" />
								</el-form-item>
							</template>

							<template v-else-if="selectedProvider === 'cos'">
								<div class="form-grid">
									<el-form-item label="App ID">
										<el-input v-model="form.cos.app_id" />
									</el-form-item>
									<el-form-item label="Region">
										<el-input v-model="form.cos.region" />
									</el-form-item>
									<el-form-item label="Secret ID">
										<el-input v-model="form.cos.secret_id" />
									</el-form-item>
									<el-form-item label="Secret Key">
										<el-input v-model="form.cos.secret_key" show-password />
									</el-form-item>
									<el-form-item label="Bucket">
										<el-input v-model="form.cos.bucket_name" />
									</el-form-item>
									<el-form-item label="Path Prefix">
										<el-input v-model="form.cos.path_prefix" />
									</el-form-item>
								</div>
							</template>

							<template v-else-if="selectedProvider === 'tos'">
								<div class="form-grid">
									<el-form-item label="Endpoint">
										<el-input v-model="form.tos.endpoint" />
									</el-form-item>
									<el-form-item label="Region">
										<el-input v-model="form.tos.region" />
									</el-form-item>
									<el-form-item label="Access Key">
										<el-input v-model="form.tos.access_key" />
									</el-form-item>
									<el-form-item label="Secret Key">
										<el-input v-model="form.tos.secret_key" show-password />
									</el-form-item>
									<el-form-item label="Bucket">
										<el-input v-model="form.tos.bucket_name" />
									</el-form-item>
									<el-form-item label="Path Prefix">
										<el-input v-model="form.tos.path_prefix" />
									</el-form-item>
								</div>
							</template>

							<template v-else-if="selectedProvider === 's3'">
								<div class="form-grid">
									<el-form-item label="Endpoint">
										<el-input v-model="form.s3.endpoint" />
									</el-form-item>
									<el-form-item label="Region">
										<el-input v-model="form.s3.region" />
									</el-form-item>
									<el-form-item label="Access Key">
										<el-input v-model="form.s3.access_key" />
									</el-form-item>
									<el-form-item label="Secret Key">
										<el-input v-model="form.s3.secret_key" show-password />
									</el-form-item>
									<el-form-item label="Bucket">
										<el-input v-model="form.s3.bucket_name" />
									</el-form-item>
									<el-form-item label="Path Prefix">
										<el-input v-model="form.s3.path_prefix" />
									</el-form-item>
								</div>
							</template>

							<template v-else-if="selectedProvider === 'oss'">
								<div class="form-grid">
									<el-form-item label="Endpoint">
										<el-input v-model="form.oss.endpoint" />
									</el-form-item>
									<el-form-item label="Region">
										<el-input v-model="form.oss.region" />
									</el-form-item>
									<el-form-item label="Access Key">
										<el-input v-model="form.oss.access_key" />
									</el-form-item>
									<el-form-item label="Secret Key">
										<el-input v-model="form.oss.secret_key" show-password />
									</el-form-item>
									<el-form-item label="Bucket">
										<el-input v-model="form.oss.bucket_name" />
									</el-form-item>
									<el-form-item label="Path Prefix">
										<el-input v-model="form.oss.path_prefix" />
									</el-form-item>
									<el-form-item label="Temp Bucket">
										<el-input v-model="form.oss.temp_bucket_name" />
									</el-form-item>
									<el-form-item label="Temp Region">
										<el-input v-model="form.oss.temp_region" />
									</el-form-item>
								</div>
								<el-form-item label="Use Temp Bucket">
									<el-switch v-model="form.oss.use_temp_bucket" />
								</el-form-item>
							</template>
						</el-form>

						<div class="config-panel__footer">
							<el-button
								link
								type="primary"
								:loading="testingProvider === selectedProvider"
								@click="testProvider(selectedProvider)"
							>
								连通测试
							</el-button>
							<el-button
								@click="reloadSelectedProvider"
								:loading="providerLoading === selectedProvider"
							>
								重新加载
							</el-button>
							<el-button type="primary" :loading="saving" @click="saveConfig">保存配置</el-button>
						</div>
					</template>
					<div v-else class="config-panel__empty">请先从左侧选择一个引擎。</div>
				</section>
			</div>
		</div>

		<template #footer>
			<div class="dialog-footer">
				<el-button @click="visible = false">关闭</el-button>
			</div>
		</template>
	</el-dialog>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { storageProvider } from '@repo/api-service'

type StorageProviderName = 'local' | 'minio' | 'cos' | 'tos' | 's3' | 'oss'

interface EngineItem {
	name: StorageProviderName
	allowed: boolean
	available: boolean
	description: string
}

interface StorageFormState {
	default_provider: StorageProviderName
	local: { provider: 'local'; path_prefix: string }
	minio: {
		provider: 'minio'
		access_key_id: string
		bucket_name: string
		endpoint: string
		mode: string
		path_prefix: string
		secret_access_key: string
		use_ssl: boolean
	}
	cos: {
		provider: 'cos'
		app_id: string
		bucket_name: string
		path_prefix: string
		region: string
		secret_id: string
		secret_key: string
	}
	tos: {
		provider: 'tos'
		access_key: string
		bucket_name: string
		endpoint: string
		path_prefix: string
		region: string
		secret_key: string
	}
	s3: {
		provider: 's3'
		access_key: string
		bucket_name: string
		endpoint: string
		path_prefix: string
		region: string
		secret_key: string
	}
	oss: {
		provider: 'oss'
		access_key: string
		bucket_name: string
		endpoint: string
		path_prefix: string
		region: string
		secret_key: string
		temp_bucket_name: string
		temp_region: string
		use_temp_bucket: boolean
	}
}

const providerNames: StorageProviderName[] = ['local', 'minio', 'cos', 'tos', 's3', 'oss']
const visible = ref(false)
const pageLoading = ref(false)
const engineLoading = ref(false)
const initLoading = ref(false)
const saving = ref(false)
const selectedProvider = ref<StorageProviderName | ''>('')
const providerLoading = ref<StorageProviderName | ''>('')
const testingProvider = ref<StorageProviderName | ''>('')
const engines = ref<EngineItem[]>([])
const loadedProviders = ref<Record<StorageProviderName, boolean>>({
	local: false,
	minio: false,
	cos: false,
	tos: false,
	s3: false,
	oss: false
})

function createDefaultForm(): StorageFormState {
	return {
		default_provider: 'local',
		local: { provider: 'local', path_prefix: '' },
		minio: {
			provider: 'minio',
			access_key_id: '',
			bucket_name: '',
			endpoint: '',
			mode: 'docker',
			path_prefix: '',
			secret_access_key: '',
			use_ssl: false
		},
		cos: {
			provider: 'cos',
			app_id: '',
			bucket_name: '',
			path_prefix: '',
			region: '',
			secret_id: '',
			secret_key: ''
		},
		tos: {
			provider: 'tos',
			access_key: '',
			bucket_name: '',
			endpoint: '',
			path_prefix: '',
			region: '',
			secret_key: ''
		},
		s3: {
			provider: 's3',
			access_key: '',
			bucket_name: '',
			endpoint: '',
			path_prefix: '',
			region: '',
			secret_key: ''
		},
		oss: {
			provider: 'oss',
			access_key: '',
			bucket_name: '',
			endpoint: '',
			path_prefix: '',
			region: '',
			secret_key: '',
			temp_bucket_name: '',
			temp_region: '',
			use_temp_bucket: false
		}
	}
}

const form = reactive<StorageFormState>(createDefaultForm())

function formatProviderLabel(name: StorageProviderName) {
	return name.toUpperCase()
}

function setLoaded(provider: StorageProviderName) {
	loadedProviders.value[provider] = true
}

function assignConfig(provider: StorageProviderName, config: Record<string, any>) {
	switch (provider) {
		case 'local':
			Object.assign(form.local, {
				provider: 'local',
				path_prefix: config.path_prefix ?? ''
			})
			break
		case 'minio':
			Object.assign(form.minio, {
				provider: 'minio',
				access_key_id: config.access_key_id ?? '',
				bucket_name: config.bucket_name ?? '',
				endpoint: config.endpoint ?? '',
				mode: config.mode ?? 'docker',
				path_prefix: config.path_prefix ?? '',
				secret_access_key: config.secret_access_key ?? '',
				use_ssl: Boolean(config.use_ssl)
			})
			break
		case 'cos':
			Object.assign(form.cos, {
				provider: 'cos',
				app_id: config.app_id ?? '',
				bucket_name: config.bucket_name ?? '',
				path_prefix: config.path_prefix ?? '',
				region: config.region ?? '',
				secret_id: config.secret_id ?? '',
				secret_key: config.secret_key ?? ''
			})
			break
		case 'tos':
			Object.assign(form.tos, {
				provider: 'tos',
				access_key: config.access_key ?? '',
				bucket_name: config.bucket_name ?? '',
				endpoint: config.endpoint ?? '',
				path_prefix: config.path_prefix ?? '',
				region: config.region ?? '',
				secret_key: config.secret_key ?? ''
			})
			break
		case 's3':
			Object.assign(form.s3, {
				provider: 's3',
				access_key: config.access_key ?? '',
				bucket_name: config.bucket_name ?? '',
				endpoint: config.endpoint ?? '',
				path_prefix: config.path_prefix ?? '',
				region: config.region ?? '',
				secret_key: config.secret_key ?? ''
			})
			break
		case 'oss':
			Object.assign(form.oss, {
				provider: 'oss',
				access_key: config.access_key ?? '',
				bucket_name: config.bucket_name ?? '',
				endpoint: config.endpoint ?? '',
				path_prefix: config.path_prefix ?? '',
				region: config.region ?? '',
				secret_key: config.secret_key ?? '',
				temp_bucket_name: config.temp_bucket_name ?? '',
				temp_region: config.temp_region ?? '',
				use_temp_bucket: Boolean(config.use_temp_bucket)
			})
			break
	}
	setLoaded(provider)
}

function extractConfig(result: Record<string, any>) {
	return result?.config && typeof result.config === 'object' ? result.config : result
}

async function loadEngines() {
	engineLoading.value = true
	try {
		const res = await storageProvider.postStorageProviderEngines({})
		if (res?.isSuccess) {
			engines.value = (res.result || [])
				.filter((item): item is EngineItem =>
					providerNames.includes(item.name as StorageProviderName)
				)
				.map((item) => ({
					name: item.name as StorageProviderName,
					allowed: Boolean(item.allowed),
					available: Boolean(item.available),
					description: item.description || ''
				}))
		}
		if (!selectedProvider.value && engines.value[0]) {
			await selectProvider(engines.value[0]!.name)
		}
	} catch {
		ElMessage.error('加载引擎失败')
	} finally {
		engineLoading.value = false
	}
}

async function handleInit() {
	initLoading.value = true
	try {
		const res = await storageProvider.postStorageProviderInitStorageProvider({})
		if (res?.isSuccess) {
			ElMessage.success('初始化成功')
			await loadEngines()
			return
		}
		ElMessage.error('初始化失败')
	} catch {
		ElMessage.error('初始化失败')
	} finally {
		initLoading.value = false
	}
}

async function loadProviderConfig(provider: StorageProviderName) {
	providerLoading.value = provider
	try {
		const res = await storageProvider.postStorageProviderConfig({ name: provider })
		if (res?.isSuccess && res.result) {
			const raw = res.result as Record<string, any>
			assignConfig(provider, extractConfig(raw))
			if (raw.is_default === true || raw.isDefault === true) {
				form.default_provider = provider
			}
			selectedProvider.value = provider
		}
	} catch {
		ElMessage.error('加载配置失败')
	} finally {
		providerLoading.value = ''
	}
}

async function selectProvider(provider: StorageProviderName) {
	selectedProvider.value = provider
	await loadProviderConfig(provider)
}

function buildCheckPayload(provider: StorageProviderName) {
	switch (provider) {
		case 'local':
			return { name: provider, config: { ...form.local } }
		case 'minio':
			return { name: provider, config: { ...form.minio } }
		case 'cos':
			return { name: provider, config: { ...form.cos } }
		case 'tos':
			return { name: provider, config: { ...form.tos } }
		case 's3':
			return { name: provider, config: { ...form.s3 } }
		case 'oss':
			return { name: provider, config: { ...form.oss } }
	}
}

async function testProvider(provider: StorageProviderName) {
	testingProvider.value = provider
	try {
		if (selectedProvider.value !== provider || !loadedProviders.value[provider]) {
			await loadProviderConfig(provider)
		}
		const res = await storageProvider.postStorageProviderCheck(buildCheckPayload(provider) as any)
		if (res?.isSuccess) {
			ElMessage.success(`${formatProviderLabel(provider)} 连通成功`)
			return
		}
		ElMessage.error(res?.error || `${formatProviderLabel(provider)} 连通失败`)
	} catch {
		ElMessage.error(`${formatProviderLabel(provider)} 连通失败`)
	} finally {
		testingProvider.value = ''
	}
}

function buildUpdatePayload() {
	return {
		default_provider: form.default_provider,
		cos: { ...form.cos },
		local: { ...form.local },
		minio: { ...form.minio },
		oss: { ...form.oss },
		s3: { ...form.s3 },
		tos: { ...form.tos }
	}
}

async function saveConfig() {
	if (!selectedProvider.value) {
		ElMessage.warning('请先选择一个引擎')
		return
	}
	saving.value = true
	try {
		const res = await storageProvider.postStorageProviderUpdate(buildUpdatePayload() as any)
		if (res?.isSuccess) {
			ElMessage.success('配置已保存')
			await loadEngines()
			return
		}
		ElMessage.error('保存失败')
	} catch {
		ElMessage.error('保存失败')
	} finally {
		saving.value = false
	}
}

async function reloadSelectedProvider() {
	if (!selectedProvider.value) return
	await loadProviderConfig(selectedProvider.value)
}

async function open() {
	visible.value = true
	pageLoading.value = true
	try {
		await loadEngines()
	} finally {
		pageLoading.value = false
	}
}

function close() {
	visible.value = false
}

defineExpose({ open, close })
</script>

<style scoped lang="less">
.storage-modal {
	display: flex;
	flex-direction: column;
	gap: 16px;
	height: 640px;
	min-height: 0;
	overflow: hidden;
}

.storage-actions {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
}

.storage-layout {
	display: grid;
	grid-template-columns: 280px minmax(0, 1fr);
	gap: 16px;
	flex: 1;
	min-height: 0;
	overflow: hidden;
}

.engine-list {
	border: 1px solid #e5e7eb;
	border-radius: 12px;
	background: #fff;
	padding: 12px;
	display: flex;
	flex-direction: column;
	gap: 12px;
	height: 100%;
	min-height: 0;
	overflow: hidden;
}

.engine-list__header {
	font-size: 14px;
	font-weight: 700;
	color: #111827;
}

.engine-list__body {
	display: flex;
	flex-direction: column;
	gap: 10px;
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	padding-right: 4px;
}

.engine-card {
	padding: 12px;
	border: 1px solid #e5e7eb;
	border-radius: 12px;
	background: #f8fafc;
	cursor: pointer;
	transition: all 0.2s ease;
}

.engine-card:hover,
.engine-card--active {
	border-color: #3b82f6;
	background: #eff6ff;
}

.engine-card__top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	margin-bottom: 8px;
}

.engine-card__name {
	font-weight: 700;
	color: #111827;
}

.engine-card__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-bottom: 8px;
}

.engine-card__desc {
	font-size: 12px;
	line-height: 1.5;
	color: #6b7280;
}

.engine-card__actions {
	display: flex;
	justify-content: flex-end;
	margin-top: 8px;
}

.config-panel {
	border: 1px solid #e5e7eb;
	border-radius: 12px;
	background: #fff;
	padding: 16px;
	display: flex;
	flex-direction: column;
	gap: 16px;
	min-height: 0;
	overflow: auto;
}

.config-panel__header {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
}

.config-panel__title {
	font-size: 16px;
	font-weight: 700;
	color: #111827;
}

.config-panel__desc {
	margin-top: 6px;
	font-size: 13px;
	color: #6b7280;
}

.config-panel__footer {
	display: flex;
	justify-content: flex-end;
	gap: 8px;
}

.config-panel__empty {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 320px;
	color: #9ca3af;
}

.form-grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 0 12px;
}

.dialog-footer {
	display: flex;
	justify-content: flex-end;
}

@media (max-width: 960px) {
	.storage-layout,
	.form-grid {
		grid-template-columns: minmax(0, 1fr);
	}
}
</style>
