<template>
	<div class="storage-manager" v-loading="pageLoading">
		<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="grid">
			<div v-for="item in engines" :key="item.name" class="card">
				<div class="card-head">
					<div class="card-head__top">
						<div class="title-block">
							<div class="title">{{ formatProviderLabel(item.name) }}</div>
							<div class="subtitle">{{ item.description || '支持对象存储配置与连通测试' }}</div>
						</div>
						<div class="actions">
							<el-dropdown>
								<span class="actions-trigger">
									<el-icon>
										<MoreFilled />
									</el-icon>
								</span>
								<template #dropdown>
									<el-dropdown-menu>
										<el-dropdown-item :disabled="currentDefaultProvider === item.name"
											@click="updateDefaultProvider(item.name)">
											{{ currentDefaultProvider === item.name ? '当前默认' : '设为默认' }}
										</el-dropdown-item>
										<el-dropdown-item @click="openEditProvider(item.name)">编辑</el-dropdown-item>
									</el-dropdown-menu>
								</template>
							</el-dropdown>
						</div>
					</div>
				</div>

				<div class="tags">
					<el-tag v-if="currentDefaultProvider === item.name" class="default-provider-tag" effect="light">
						默认
					</el-tag>
					<el-tag :type="item.allowed ? 'success' : 'info'" effect="light">
						{{ item.allowed ? '允许' : '不允许' }}
					</el-tag>
					<el-tag :type="item.available ? 'primary' : 'warning'" effect="light">
						{{ item.available ? '可用' : '不可用' }}
					</el-tag>
				</div>
			</div>
			<el-empty v-if="!engines.length" class="empty" description="暂无引擎" />
		</div>


		<el-drawer v-model="drawerVisible"
			:title="selectedProvider ? `${formatProviderLabel(selectedProvider)} 配置` : '编辑存储引擎'" direction="rtl" size="760px">
			<template v-if="selectedProvider">
				<div class="drawer-intro">
					<div class="drawer-intro__title">{{ formatProviderLabel(selectedProvider) }}</div>
					<div class="drawer-intro__desc">修改当前存储引擎配置后保存，可直接在此执行重新加载与连通测试。</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>
			</template>

			<template #footer>
				<div class="drawer-footer">
					<el-button @click="drawerVisible = false">取消</el-button>
					<el-button @click="reloadSelectedProvider" :loading="providerLoading === selectedProvider">
						重新加载
					</el-button>
					<el-button type="primary" plain :disabled="!selectedProvider"
						:loading="selectedProvider ? testingProvider === selectedProvider : false"
						@click="selectedProvider && testProvider(selectedProvider)">
						测试连接
					</el-button>
					<el-button type="primary" :loading="saving" @click="saveConfig">保存配置</el-button>
				</div>
			</template>
		</el-drawer>
	</div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { MoreFilled } from '@element-plus/icons-vue'
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 pageLoading = ref(false)
const engineLoading = ref(false)
const initLoading = ref(false)
const saving = ref(false)
const drawerVisible = ref(false)
const selectedProvider = ref<StorageProviderName | ''>('')
const providerLoading = ref<StorageProviderName | ''>('')
const testingProvider = ref<StorageProviderName | ''>('')
const settingDefaultProvider = ref<StorageProviderName | ''>('')
const engines = ref<EngineItem[]>([])
const currentDefaultProvider = ref<StorageProviderName | ''>('')
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 || ''
				}))
		}
	} catch {
		ElMessage.error('加载引擎失败')
	} finally {
		engineLoading.value = false
	}
}

async function loadDefaultProvider() {
	try {
		const res = await storageProvider.postStorageProviderDefaultProvider({})
		if (res?.isSuccess && res.result && providerNames.includes(res.result as StorageProviderName)) {
			currentDefaultProvider.value = res.result as StorageProviderName
			form.default_provider = res.result as StorageProviderName
			return
		}
		currentDefaultProvider.value = ''
	} catch {
		ElMessage.error('获取默认存储厂商失败')
	}
}

async function handleInit() {
	initLoading.value = true
	try {
		const res = await storageProvider.postStorageProviderInitStorageProvider({})
		if (res?.isSuccess) {
			ElMessage.success('初始化成功')
			await Promise.all([loadEngines(), loadDefaultProvider()])
			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))
			selectedProvider.value = provider
		}
	} catch {
		ElMessage.error('加载配置失败')
	} finally {
		providerLoading.value = ''
	}
}

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

async function openEditProvider(provider: StorageProviderName) {
	await selectProvider(provider)
	drawerVisible.value = true
}

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 = ''
	}
}

async function updateDefaultProvider(provider: StorageProviderName) {
	settingDefaultProvider.value = provider
	try {
		const res = await storageProvider.postStorageProviderUpdateDefaultProvider({ provider })
		if (res?.isSuccess) {
			currentDefaultProvider.value = provider
			form.default_provider = provider
			ElMessage.success('默认存储厂商已更新')
			return
		}
		ElMessage.error('默认存储厂商更新失败')
	} catch {
		ElMessage.error('默认存储厂商更新失败')
	} finally {
		settingDefaultProvider.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 ensureAllConfigsLoaded() {
	for (const provider of providerNames) {
		if (loadedProviders.value[provider]) continue
		await loadProviderConfig(provider)
	}
}

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

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

onMounted(async () => {
	pageLoading.value = true
	try {
		await Promise.all([loadEngines(), loadDefaultProvider()])
	} finally {
		pageLoading.value = false
	}
})
</script>

<style scoped lang="less">
.storage-manager {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

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

.grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
	gap: 16px;
	min-height: 240px;

	.empty {
		grid-column: span 4;
	}
}

.card {
	overflow: hidden;
	padding: 16px;
	border: 1px solid #e5e7eb;
	border-radius: 20px;
	background: #fff;
	display: flex;
	flex-direction: column;
	gap: 14px;
	box-shadow: 0 12px 28px rgba(15, 23, 42, 0.06);
	transition:
		transform 0.22s ease,
		box-shadow 0.22s ease,
		border-color 0.22s ease;
}

.card:hover {
	transform: translateY(-3px);
	border-color: #d8dee9;
	box-shadow: 0 18px 36px rgba(15, 23, 42, 0.1);
}

.card-head {
	padding: 14px 16px;
	border-radius: 18px;
	background:
		radial-gradient(circle at top left, rgba(15, 23, 42, 0.06), transparent 38%),
		linear-gradient(135deg, #f8fafc, #eef2ff 58%, #fff7ed);
}

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

.title-block {
	min-width: 0;
}

.title {
	font-size: 18px;
	font-weight: 700;
	line-height: 1.25;
	color: #0f172a;
	word-break: break-word;
}

.subtitle {
	margin-top: 6px;
	font-size: 13px;
	color: #64748b;
	line-height: 1.6;
}

.badge-row {
	margin-top: 10px;
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.badge {
	padding: 5px 10px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.92);
	font-size: 12px;
	color: #334155;
	border: 1px solid rgba(203, 213, 225, 0.9);
}

.badge.subtle {
	background: rgba(15, 23, 42, 0.82);
	color: #f8fafc;
	border-color: transparent;
}

.tags {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.actions {
	display: flex;
	justify-content: flex-end;
}

.actions-trigger {
	width: 30px;
	height: 30px;
	border-radius: 999px;
	display: grid;
	place-items: center;
	color: #475569;
	background: rgba(255, 255, 255, 0.8);
	transition:
		background 0.2s ease,
		color 0.2s ease;
}

.actions-trigger:hover {
	background: rgba(15, 23, 42, 0.08);
	color: #0f172a;
}

.drawer-intro {
	padding: 16px;
	border-radius: 18px;
	background:
		radial-gradient(circle at top left, rgba(15, 23, 42, 0.06), transparent 38%),
		linear-gradient(135deg, #f8fafc, #eef2ff 58%, #fff7ed);
	margin-bottom: 16px;
}

.drawer-intro__title {
	font-size: 16px;
	font-weight: 700;
	color: #111827;
}

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

.drawer-footer {
	display: flex;
	justify-content: flex-end;
	gap: 8px;
	flex-wrap: wrap;
}

:deep(.default-provider-tag.el-tag) {
	color: #1d4ed8;
	background: #dbeafe;
	border-color: #93c5fd;
}

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

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