<template>
	<div class="assets-edit-asset-container">
		<el-dialog :title="isEdit ? '修改资产' : '新增资产'" v-model="isShowDialog" width="1000px" destroy-on-close>
			<el-form ref="formRef" :model="ruleForm" :rules="rules" size="default" label-width="100px" v-loading="formLoading">
				<!-- 基础信息 -->
				<el-divider content-position="left">基础信息</el-divider>
				<el-row :gutter="24">
					<el-col :span="8">
						<el-form-item label="资产名称" prop="name">
							<el-input v-model="ruleForm.name" placeholder="请输入资产名称" clearable />
						</el-form-item>
					</el-col>
					<el-col :span="8">
						<el-form-item label="资产类型" prop="type">
							<el-select v-model="ruleForm.type" placeholder="请选择资产类型" class="w100" :disabled="isEdit">
								<el-option label="实物" value="physical" />
								<el-option label="虚拟" value="virtual" />
								<el-option label="服务" value="service" />
							</el-select>
						</el-form-item>
					</el-col>
					<el-col :span="8">
						<el-form-item label="资产分类" prop="categoryId">
							<el-cascader
								v-model="ruleForm.categoryId"
								:options="categoryOptions"
								:props="categoryProps"
								placeholder="请选择资产分类"
								clearable
								class="w100"
								:disabled="isEdit"
								@change="onCategoryChange"
							/>
						</el-form-item>
					</el-col>
				</el-row>
				<el-row :gutter="24">
					<el-col :span="8">
						<el-form-item label="上线时间">
							<el-date-picker
								v-model="ruleForm.onlineTime"
								type="datetime"
								placeholder="请选择上线时间"
								format="YYYY-MM-DD HH:mm:ss"
								value-format="YYYY-MM-DD HH:mm:ss"
								class="w100"
								@change="onOnlineTimeChange"
							/>
						</el-form-item>
					</el-col>
					<el-col :span="8">
						<el-form-item label="下线时间">
							<el-date-picker
								v-model="ruleForm.offlineTime"
								type="datetime"
								placeholder="请选择下线时间"
								format="YYYY-MM-DD HH:mm:ss"
								value-format="YYYY-MM-DD HH:mm:ss"
								class="w100"
								:disabled-date="disabledOfflineDate"
							/>
						</el-form-item>
					</el-col>
					<el-col :span="8">
						<el-form-item label="库存类型">
							<el-radio-group v-model="ruleForm.unlimitedStock" :disabled="isEdit">
								<el-radio :value="false">有限库存</el-radio>
								<el-radio :value="true">无限库存</el-radio>
							</el-radio-group>
						</el-form-item>
					</el-col>
					<el-col :span="8" v-if="tenantId == 1">
						<el-form-item label="存储模式">
							<el-radio-group v-model="ruleForm.stockMode" :disabled="isEdit">
								<el-radio :value="1">明细模式</el-radio>
								<el-radio :value="2">批次模式</el-radio>
							</el-radio-group>
						</el-form-item>
					</el-col>
				</el-row>

				<!-- 分类属性值选择 -->
				<template v-if="categoryAttrs.length > 0">
					<el-divider content-position="left">分类属性</el-divider>
					<el-row :gutter="24">
						<el-col :span="8" v-for="(attr, index) in categoryAttrs" :key="index">
							<el-form-item
								:label="getAttrLabel(attr)"
								:prop="'metadata.' + getAttrKey(attr)"
								:rules="[{ required: !!attr.required, message: getAttrLabel(attr) + '不能为空', trigger: ['blur', 'change'] }]"
							>
								<!-- 单选类型 -->
								<el-select
									v-if="attr.type === 'select'"
									v-model="ruleForm.metadata[getAttrKey(attr)]"
									:placeholder="'请选择' + getAttrLabel(attr)"
									class="w100"
									clearable
								>
									<el-option v-for="opt in attr.options" :key="opt.value" :label="opt.label" :value="opt.value" />
								</el-select>
								<!-- 多选类型 -->
								<el-select
									v-else-if="attr.type === 'multi_select'"
									v-model="ruleForm.metadata[getAttrKey(attr)]"
									:placeholder="'请选择' + getAttrLabel(attr)"
									class="w100"
									multiple
									clearable
								>
									<el-option v-for="opt in attr.options" :key="opt.value" :label="opt.label" :value="opt.value" />
								</el-select>
								<!-- 文本类型 -->
								<el-input
									v-else-if="attr.type === 'text'"
									v-model="ruleForm.metadata[getAttrKey(attr)]"
									:placeholder="'请输入' + getAttrLabel(attr)"
								/>
								<!-- 数字类型 -->
								<el-input-number v-else-if="attr.type === 'number'" v-model="ruleForm.metadata[getAttrKey(attr)]" class="w100" />
								<!-- 日期类型 -->
								<el-date-picker
									v-else-if="attr.type === 'date'"
									v-model="ruleForm.metadata[getAttrKey(attr)]"
									type="date"
									:placeholder="'请选择' + getAttrLabel(attr)"
									class="w100"
								/>
								<!-- 布尔类型 -->
								<el-switch v-else-if="attr.type === 'boolean'" v-model="ruleForm.metadata[getAttrKey(attr)]" />
								<!-- 图片类型 -->
								<div v-else-if="attr.type === 'image'" class="w100">
									<el-upload
										class="attr-image-uploader"
										:show-file-list="false"
										:auto-upload="true"
										accept="image/*"
										:http-request="onAttrImageUpload(attr)"
									>
										<img
											v-if="ruleForm.metadata[getAttrKey(attr)]"
											:src="formatImageUrl(ruleForm.metadata[getAttrKey(attr)])"
											class="avatar"
											style="width: 80px; height: 80px"
										/>
										<el-icon v-else class="avatar-uploader-icon" style="width: 80px; height: 80px; line-height: 80px"><Plus /></el-icon>
									</el-upload>
									<el-button
										v-if="ruleForm.metadata[getAttrKey(attr)]"
										type="danger"
										link
										size="small"
										@click.stop="removeAttrImage(attr)"
										style="margin-top: 5px"
									>
										删除图片
									</el-button>
								</div>
							</el-form-item>
						</el-col>
					</el-row>
				</template>

				<!-- 图片上传 -->
				<el-divider content-position="left">图片信息</el-divider>
				<el-row :gutter="24">
					<el-col :span="8">
						<el-form-item label="主图" prop="mainImage">
							<div class="w100">
								<el-upload class="avatar-uploader" :show-file-list="false" :auto-upload="true" :http-request="handleMainImageUpload" accept="image/*">
									<img v-if="mainImagePreview" :src="mainImagePreview" class="avatar" />
									<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
								</el-upload>
								<div v-if="mainImagePreview" style="margin-top: 5px">
									<el-button type="primary" link size="small" @click.stop="previewMainImage">预览</el-button>
									<el-button type="danger" link size="small" @click.stop="removeMainImage">删除</el-button>
								</div>
							</div>
						</el-form-item>
					</el-col>
					<el-col :span="16">
						<el-form-item label="图片列表">
							<el-upload
								v-model:file-list="imageFileList"
								list-type="picture-card"
								:auto-upload="true"
								:http-request="handleImageListUpload"
								:on-preview="handlePictureCardPreview"
								:on-remove="handleRemove"
								accept="image/*"
								multiple
							>
								<el-icon><Plus /></el-icon>
							</el-upload>
						</el-form-item>
					</el-col>
				</el-row>

				<!-- 资产描述 -->
				<el-divider content-position="left">资产描述</el-divider>
				<el-form-item label="描述内容" label-width="100px">
					<div class="editor-wrapper">
						<Editor v-model="ruleForm.description" height="200px" placeholder="请输入资产描述" />
					</div>
				</el-form-item>

				<!-- 实物资产配置 -->
				<template v-if="ruleForm.type === 'physical'">
					<el-divider content-position="left">实物资产配置</el-divider>
					<el-row :gutter="24">
						<el-col :span="8">
							<el-form-item label="配送方式">
								<el-select v-model="ruleForm.physicalAssetConfig.shipping.deliveryMethod" placeholder="请选择配送方式" class="w100">
									<el-option label="快递" value="express" />
									<el-option label="自提" value="self_pickup" />
									<el-option label="同城配送" value="city_delivery" disabled />
								</el-select>
							</el-form-item>
						</el-col>
					</el-row>
				</template>

				<!-- 虚拟资产配置 -->
				<template v-if="ruleForm.type === 'virtual'">
					<el-divider content-position="left">虚拟资产配置</el-divider>

					<!-- 虚拟类型选择 -->
					<el-row :gutter="24">
						<el-col :span="8">
							<el-form-item label="虚拟类型" prop="virtualAssetConfig.virtualType">
								<el-select v-model="ruleForm.virtualAssetConfig.virtualType" placeholder="请选择虚拟类型" class="w100">
									<el-option label="充值" value="recharge" />
									<el-option label="订阅" value="subscribe" />
								</el-select>
							</el-form-item>
						</el-col>
						<el-col :span="8" v-if="ruleForm.virtualAssetConfig.virtualType === 'subscribe'">
							<el-form-item label="合集价格" prop="virtualAssetConfig.collectionPrice">
								<el-input-number v-model="ruleForm.virtualAssetConfig.collectionPrice" :min="0" :precision="0" class="w100" />
								<span class="unit-text">分</span>
							</el-form-item>
						</el-col>
						<el-col :span="8">
							<el-form-item label="货币单位" prop="virtualAssetConfig.currency">
								<el-select v-model="ruleForm.virtualAssetConfig.currency" placeholder="请选择货币单位" class="w100">
									<el-option label="人民币 (CNY)" value="CNY" />
									<el-option label="美元 (USD)" value="USD" />
								</el-select>
							</el-form-item>
						</el-col>
					</el-row>

					<!-- API 配置 -->
					<el-divider content-position="left">API 配置</el-divider>
					<el-row :gutter="24">
						<el-col :span="8">
							<el-form-item label="请求方式" prop="virtualAssetConfig.apiConfig.method">
								<el-select v-model="ruleForm.virtualAssetConfig.apiConfig.method" placeholder="请选择请求方式" class="w100">
									<el-option label="GET" value="GET" />
									<el-option label="POST" value="POST" />
									<el-option label="PUT" value="PUT" />
								</el-select>
							</el-form-item>
						</el-col>
						<el-col :span="16">
							<el-form-item label="请求地址" prop="virtualAssetConfig.apiConfig.requestURL">
								<el-input v-model="ruleForm.virtualAssetConfig.apiConfig.requestURL" placeholder="请输入请求地址" class="w100" />
							</el-form-item>
						</el-col>
					</el-row>
					<el-row :gutter="24">
						<el-col :span="24">
							<el-form-item label="请求头">
								<div class="config-list-container">
									<div v-for="(item, index) in ruleForm.virtualAssetConfig.apiConfig.headers" :key="index" class="config-list-item">
										<el-input v-model="item.key" placeholder="Key" style="width: 200px" />
										<span class="separator">:</span>
										<el-input v-model="item.value" placeholder="Value" style="width: 200px" />
										<el-button
											type="danger"
											:icon="Delete"
											circle
											size="small"
											@click="removeKeyValuePair(ruleForm.virtualAssetConfig.apiConfig.headers, index)"
										/>
									</div>
									<el-button type="primary" :icon="Plus" size="small" @click="addKeyValuePair(ruleForm.virtualAssetConfig.apiConfig.headers)"
										>添加请求头</el-button
									>
								</div>
							</el-form-item>
						</el-col>
					</el-row>
					<el-row :gutter="24">
						<el-col :span="24">
							<el-form-item label="请求参数">
								<div class="config-list-container">
									<div v-for="(item, index) in ruleForm.virtualAssetConfig.apiConfig.params" :key="index" class="config-list-item">
										<el-input v-model="item.key" placeholder="Key" style="width: 200px" />
										<span class="separator">:</span>
										<el-input v-model="item.value" placeholder="Value" style="width: 200px" />
										<el-button
											type="danger"
											:icon="Delete"
											circle
											size="small"
											@click="removeKeyValuePair(ruleForm.virtualAssetConfig.apiConfig.params, index)"
										/>
									</div>
									<el-button type="primary" :icon="Plus" size="small" @click="addKeyValuePair(ruleForm.virtualAssetConfig.apiConfig.params)"
										>添加请求参数</el-button
									>
								</div>
							</el-form-item>
						</el-col>
					</el-row>
					<el-row :gutter="24">
						<el-col :span="8">
							<el-form-item label="认证方式" prop="virtualAssetConfig.apiConfig.authType">
								<el-select v-model="ruleForm.virtualAssetConfig.apiConfig.authType" placeholder="请选择认证方式" class="w100">
									<el-option label="无" value="none" />
									<el-option label="API Key" value="apikey" />
									<el-option label="Bearer Token" value="bearer" />
									<el-option label="OAuth" value="oauth" />
								</el-select>
							</el-form-item>
						</el-col>
						<el-col :span="16" v-if="ruleForm.virtualAssetConfig.apiConfig.authType !== 'none'">
							<el-form-item label="认证配置" prop="virtualAssetConfig.apiConfig.authConfig">
								<el-input
									v-model="ruleForm.virtualAssetConfig.apiConfig.authConfig"
									type="textarea"
									:rows="2"
									placeholder="请输入认证配置"
									class="w100"
								/>
							</el-form-item>
						</el-col>
					</el-row>
				</template>

				<!-- 服务资产配置 -->
				<template v-if="ruleForm.type === 'service'">
					<el-divider content-position="left">服务资产配置</el-divider>

					<!-- 服务类型选择 -->
					<el-row :gutter="24">
						<el-col :span="8">
							<el-form-item label="服务类型" prop="serviceAssetConfig.serviceAssetType">
								<el-select v-model="ruleForm.serviceAssetConfig.serviceAssetType" placeholder="请选择服务类型" class="w100">
									<el-option label="到店" value="arrival" />
									<el-option label="上门" value="visit" disabled />
								</el-select>
							</el-form-item>
						</el-col>
					</el-row>

					<!-- 到店服务配置 -->
					<template v-if="ruleForm.serviceAssetConfig.serviceAssetType === 'arrival'">
						<!-- 预订配置 -->
						<el-row :gutter="24">
							<el-col :span="6">
								<el-form-item label="最小提前" prop="serviceAssetConfig.serviceAssetArrivalConfig.booking.minAdvance">
									<el-input-number v-model="ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.booking.minAdvance" :min="0" class="w100" />
									<span class="unit-text">分钟</span>
								</el-form-item>
							</el-col>
							<el-col :span="6">
								<el-form-item label="最小时长" prop="serviceAssetConfig.serviceAssetArrivalConfig.booking.minDuration">
									<el-input-number v-model="ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.booking.minDuration" :min="0" class="w100" />
									<span class="unit-text">分钟</span>
								</el-form-item>
							</el-col>
							<el-col :span="6">
								<el-form-item label="取消提前" prop="serviceAssetConfig.serviceAssetArrivalConfig.booking.cancelWindow">
									<el-input-number v-model="ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.booking.cancelWindow" :min="0" class="w100" />
									<span class="unit-text">分钟</span>
								</el-form-item>
							</el-col>
						</el-row>

						<!-- 时间段配置 -->
						<el-form-item label="服务时间" prop="serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots">
							<div class="config-list-container">
								<div
									v-for="(slot, index) in ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots"
									:key="index"
									class="config-list-item"
								>
									<el-select v-model="slot.dayOfWeek" placeholder="星期" style="width: 100px">
										<el-option v-for="d in 7" :key="d" :label="'周' + ['一', '二', '三', '四', '五', '六', '日'][d - 1]" :value="String(d)" />
									</el-select>
									<el-time-picker v-model="slot.startTime" format="HH:mm" value-format="HH:mm" placeholder="开始" style="width: 100px" />
									<span class="separator">-</span>
									<el-time-picker v-model="slot.endTime" format="HH:mm" value-format="HH:mm" placeholder="结束" style="width: 100px" />
									<el-input-number v-model="slot.capacity" :min="1" placeholder="容量" style="width: 100px" controls-position="right" />
									<el-button type="danger" :icon="Delete" circle size="small" @click="removeTimeSlot(index)" />
								</div>
								<el-button type="primary" :icon="Plus" size="small" @click="addTimeSlot" :disabled="isTimeSlotLimitReached"> 添加时间段 </el-button>
							</div>
						</el-form-item>

						<!-- 例外日期配置 -->
						<el-form-item label="休息时间">
							<div class="config-list-container">
								<div
									v-for="(exc, index) in ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.exceptions"
									:key="index"
									class="config-list-item"
								>
									<el-select v-model="exc.exceptionType" placeholder="类型" style="width: 100px" @change="onExceptionTypeChange(exc)">
										<el-option label="指定日期" value="date" />
										<el-option label="指定星期" value="dayOfWeek" />
									</el-select>
									<el-date-picker
										v-if="exc.exceptionType === 'date'"
										v-model="exc.date"
										type="date"
										format="YYYY-MM-DD"
										value-format="YYYY-MM-DD"
										placeholder="日期"
										style="width: 130px"
									/>
									<el-select v-if="exc.exceptionType === 'dayOfWeek'" v-model="exc.dayOfWeek" placeholder="星期" style="width: 100px">
										<el-option v-for="d in 7" :key="d" :label="'周' + ['一', '二', '三', '四', '五', '六', '日'][d - 1]" :value="String(d)" />
									</el-select>
									<el-select v-model="exc.status" placeholder="状态" style="width: 90px">
										<el-option label="可用" :value="1" />
										<el-option label="不可用" :value="0" />
									</el-select>
									<el-input v-model="exc.reason" placeholder="原因" style="width: 120px" />
									<el-button type="danger" :icon="Delete" circle size="small" @click="removeException(index)" />
								</div>
								<el-button type="primary" :icon="Plus" size="small" @click="addException">添加休息时间</el-button>
							</div>
						</el-form-item>
					</template>
				</template>
			</el-form>
			<template #footer>
				<span class="dialog-footer">
					<el-button @click="onCancel" size="default">取 消</el-button>
					<el-button type="primary" @click="onSubmit" size="default" :loading="submitLoading">{{ isEdit ? '修 改' : '添 加' }}</el-button>
				</span>
			</template>
		</el-dialog>

		<!-- 图片预览 -->
		<el-dialog v-model="dialogVisible" title="图片预览">
			<img :src="dialogImageUrl" style="width: 100%" />
		</el-dialog>
	</div>
</template>

<script lang="ts">
export default {
	name: 'assetsEditAsset',
};
</script>

<script setup lang="ts">
import { ref, reactive, watch, computed } from 'vue';
import { ElMessage } from 'element-plus';
import type { FormInstance, FormRules } from 'element-plus';
import { Plus, Delete } from '@element-plus/icons-vue';
import { getAsset, createAsset, updateAsset, uploadAssetImage } from '/@/api/assets/asset';
import { getCategoryTree, getCategory } from '/@/api/assets/category';
import { createFormDiff } from '/@/utils/diffUtils';
import { Session } from '/@/utils/storage';
import Editor from '/@/components/editor/index.vue';
import type { UploadFile, UploadUserFile, UploadRequestOptions } from 'element-plus';

// 类型定义
interface TimeSlot {
	dayOfWeek: string;
	startTime: string;
	endTime: string;
	capacity: number;
}

interface Exception {
	exceptionType: 'date' | 'dayOfWeek';
	date: string;
	status: number;
	reason: string;
	dayOfWeek: string;
}

interface CategoryAttr {
	name: string;
	type: string;
	options?: { label: string; value: string }[];
	required?: boolean;
	dictType?: string;
}

interface KeyValuePair {
	key: string;
	value: string;
}

interface RuleForm {
	id: string;
	name: string;
	type: string;
	categoryId: string;
	categoryPath: string;
	description: string;
	onlineTime: string;
	offlineTime: string;
	unlimitedStock: boolean;
	stockMode: number;
	physicalAssetConfig: {
		shipping: {
			deliveryMethod: string;
			deliveryTime: number;
		};
	};
	virtualAssetConfig: {
		virtualType: string;
		collectionPrice: number;
		currency: string;
		apiConfig: {
			method: string;
			requestURL: string;
			headers: KeyValuePair[];
			params: KeyValuePair[];
			authType: string;
			authConfig: string;
		};
	};
	serviceAssetConfig: {
		serviceAssetType: string;
		serviceAssetArrivalConfig: {
			schedule: {
				timeSlots: TimeSlot[];
				exceptions: Exception[];
			};
			booking: {
				minAdvance: number;
				minDuration: number;
				cancelWindow: number;
			};
			capacity: {
				maxUsers: number;
			};
		};
	};
	metadata: Record<string, any>;
	mainImage?: string;
}

const emit = defineEmits(['getAssetList']);

const formRef = ref<FormInstance>();
const editAssetRef = ref();
const MAX_TIME_SLOTS = 7;
const isShowDialog = ref(false);
const isEdit = ref(false);
const submitLoading = ref(false);
const formLoading = ref(false);
const categoryOptions = ref<any[]>([]);
const categoryAttrs = ref<CategoryAttr[]>([]);

// 分类选择器配置 - 只能选择最下级节点(isLeafNode: true)
const categoryProps = {
	checkStrictly: true,
	emitPath: false,
	value: 'id',
	label: 'name',
	children: 'children',
	disabled: (data: any) => !data.isLeafNode,
};
const isTimeSlotLimitReached = computed(() => ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots.length >= MAX_TIME_SLOTS);

// 获取属性的key
const getAttrKey = (attr: CategoryAttr): string => {
	return attr.name || `attr_${categoryAttrs.value.indexOf(attr)}`;
};

// 获取属性的显示名称
const getAttrLabel = (attr: CategoryAttr): string => {
	return attr.name || '属性';
};

// 图片相关
const mainImagePreview = ref('');
const imageFileList = ref<UploadUserFile[]>([]);
const dialogVisible = ref(false);
const dialogImageUrl = ref('');
// 图片拼接
const fileAddressPrefix = ref('');
// 使用通用工具函数保存原始数据，用于最小化传参
const assetFormDiff = createFormDiff<Record<string, any>>();

// 获取租户ID
const tenantId = ref(Session.get('userInfo')?.tenantId || '');

const formatImageUrl = (url?: string) => {
	if (!url) return '';
	if (/^https?:\/\//i.test(url)) return url;
	if (/^blob:/i.test(url)) return url; // 支持本地预览地址
	return `${fileAddressPrefix.value || ''}${url}`;
};

const createDefaultTimeSlots = (): TimeSlot[] => {
	const slots: TimeSlot[] = [];
	for (let i = 1; i <= MAX_TIME_SLOTS; i++) {
		slots.push({
			dayOfWeek: String(i),
			startTime: '09:00',
			endTime: '18:00',
			capacity: 100,
		});
	}
	return slots;
};

// 初始表单数据
const getInitialForm = (): RuleForm => ({
	id: '',
	name: '',
	type: 'physical',
	categoryId: '',
	categoryPath: '',
	description: '',
	onlineTime: '',
	offlineTime: '',
	unlimitedStock: false,
	stockMode: 1,
	physicalAssetConfig: {
		shipping: {
			deliveryMethod: 'express',
			deliveryTime: 24,
		},
	},
	virtualAssetConfig: {
		virtualType: 'recharge',
		collectionPrice: 0,
		currency: 'CNY',
		apiConfig: {
			method: 'GET',
			requestURL: '',
			headers: [],
			params: [],
			authType: 'none',
			authConfig: '',
		},
	},
	serviceAssetConfig: {
		serviceAssetType: 'arrival',
		serviceAssetArrivalConfig: {
			schedule: {
				timeSlots: createDefaultTimeSlots(),
				exceptions: [],
			},
			booking: {
				minAdvance: 60,
				minDuration: 30,
				cancelWindow: 30,
			},
			capacity: {
				maxUsers: 0,
			},
		},
	},
	metadata: {},
	mainImage: '',
});

const ruleForm = reactive<RuleForm>(getInitialForm());

const validateOfflineTime = (_rule: any, value: string, callback: Function) => {
	if (value && ruleForm.onlineTime && new Date(value).getTime() < new Date(ruleForm.onlineTime).getTime()) {
		callback(new Error('下线时间不能早于上线时间'));
	} else {
		callback();
	}
};

const disabledOfflineDate = (time: Date) => {
	if (!ruleForm.onlineTime) return false;
	return time.getTime() < new Date(ruleForm.onlineTime).setHours(0, 0, 0, 0);
};

const validateTimeSlots = (_rule: any, value: TimeSlot[], callback: Function) => {
	if (!value || value.length === 0) {
		callback(new Error('请至少添加一个服务时间段'));
		return;
	}
	for (let i = 0; i < value.length; i++) {
		const slot = value[i];
		if (!slot.dayOfWeek || !slot.startTime || !slot.endTime || !slot.capacity) {
			callback(new Error(`第 ${i + 1} 行服务时间配置不完整`));
			return;
		}
	}
	callback();
};

const onOnlineTimeChange = () => {
	if (ruleForm.offlineTime) {
		formRef.value?.validateField('offlineTime');
	}
};

const rules: FormRules = {
	name: [{ required: true, message: '资产名称不能为空', trigger: 'blur' }],
	type: [{ required: true, message: '请选择资产类型', trigger: 'change' }],
	categoryId: [{ required: true, message: '请选择资产分类', trigger: 'change' }],
	offlineTime: [{ validator: validateOfflineTime, trigger: 'change' }],
	mainImage: [{ required: true, message: '请上传主图', trigger: 'change' }],
	'serviceAssetConfig.serviceAssetArrivalConfig.booking.minAdvance': [{ required: true, message: '请输入最小提前时间', trigger: 'blur' }],
	'serviceAssetConfig.serviceAssetArrivalConfig.booking.minDuration': [{ required: true, message: '请输入最小时长', trigger: 'blur' }],
	'serviceAssetConfig.serviceAssetArrivalConfig.booking.cancelWindow': [{ required: true, message: '请输入取消提前时间', trigger: 'blur' }],
	'serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots': [{ validator: validateTimeSlots, trigger: 'change' }],
};

// 主图上传处理
const handleMainImageUpload = async (options: UploadRequestOptions) => {
	try {
		const url = await uploadImage(options.file);
		if (url) {
			ruleForm.mainImage = url;
			mainImagePreview.value = formatImageUrl(url);
			formRef.value?.validateField('mainImage');
		}
	} catch (error) {
		ElMessage.error('主图上传失败');
	}
};

// 图片列表上传处理
const handleImageListUpload = async (options: UploadRequestOptions) => {
	try {
		const url = await uploadImage(options.file);
		if (url) {
			const fileItem = imageFileList.value.find((f) => f.uid === options.file.uid);
			if (fileItem) {
				fileItem.url = formatImageUrl(url);
				fileItem.status = 'success';
				fileItem.response = url; // 存储原始 URL
			}
		}
	} catch (error) {
		ElMessage.error('上传失败');
		const index = imageFileList.value.findIndex((f) => f.uid === options.file.uid);
		if (index !== -1) {
			imageFileList.value.splice(index, 1);
		}
	}
};

// 属性图片上传处理
const onAttrImageUpload = (attr: CategoryAttr) => {
	return async (options: UploadRequestOptions) => {
		try {
			const url = await uploadImage(options.file);
			if (url) {
				const key = getAttrKey(attr);
				ruleForm.metadata[key] = url;
				formRef.value?.validateField(`metadata.${key}`);
			}
		} catch (error) {
			ElMessage.error('图片上传失败');
		}
	};
};

// 主图预览
const previewMainImage = () => {
	if (mainImagePreview.value) {
		dialogImageUrl.value = mainImagePreview.value;
		dialogVisible.value = true;
	}
};

// 主图删除
const removeMainImage = () => {
	mainImagePreview.value = '';
	ruleForm.mainImage = '';
	formRef.value?.validateField('mainImage');
};

// 图片列表预览
const handlePictureCardPreview = (file: UploadFile) => {
	dialogImageUrl.value = file.url || '';
	dialogVisible.value = true;
};

// 图片列表移除
const handleRemove = (file: UploadFile) => {
	const index = imageFileList.value.findIndex((f) => f.uid === file.uid);
	if (index > -1) {
		imageFileList.value.splice(index, 1);
	}
};

// 移除属性图片
const removeAttrImage = (attr: CategoryAttr) => {
	const key = getAttrKey(attr);
	ruleForm.metadata[key] = '';
	formRef.value?.validateField(`metadata.${key}`);
};

// 时间段操作
const addTimeSlot = () => {
	if (!ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule) {
		ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule = { timeSlots: [], exceptions: [] };
	}
	if (!ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots) {
		ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots = [];
	}
	ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots.push({
		dayOfWeek: '1',
		startTime: '09:00',
		endTime: '18:00',
		capacity: 100,
	});
	formRef.value?.validateField('serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots');
};

const removeTimeSlot = (index: number) => {
	ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots.splice(index, 1);
	formRef.value?.validateField('serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots');
};

// 例外日期操作
const addException = () => {
	if (!ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule) {
		ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule = { timeSlots: [], exceptions: [] };
	}
	if (!ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.exceptions) {
		ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.exceptions = [];
	}
	ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.exceptions.push({
		exceptionType: 'date',
		date: '',
		status: 1,
		reason: '',
		dayOfWeek: '1',
	});
};

const removeException = (index: number) => {
	ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.exceptions.splice(index, 1);
};

// 例外类型切换时清空对应字段
const onExceptionTypeChange = (exc: Exception) => {
	if (exc.exceptionType === 'date') {
		exc.dayOfWeek = '';
	} else {
		exc.date = '';
	}
};

// 键值对操作
const addKeyValuePair = (list: KeyValuePair[]) => {
	list.push({ key: '', value: '' });
};

const removeKeyValuePair = (list: KeyValuePair[], index: number) => {
	list.splice(index, 1);
};

// 重置表单
const resetForm = () => {
	const initial = getInitialForm();
	Object.assign(ruleForm, initial);
	mainImagePreview.value = '';
	imageFileList.value = [];
	categoryAttrs.value = [];
	fileAddressPrefix.value = '';
};

// 获取分类数据
const fetchCategories = () => {
	getCategoryTree()
		.then((res: any) => {
			const tree = res.data?.tree ?? [];
			categoryOptions.value = tree.length > 0 && tree[0].children ? tree[0].children : tree;
		})
		.catch(() => {
			categoryOptions.value = [];
		});
};

// 递归查找分类节点
const findCategoryNode = (nodes: any[], id: string): any => {
	for (const node of nodes) {
		if (node.id === id) return node;
		if (node.children?.length) {
			const found = findCategoryNode(node.children, id);
			if (found) return found;
		}
	}
	return null;
};

// 分类变更时获取分类属性和path
const onCategoryChange = (categoryId: string) => {
	categoryAttrs.value = [];
	ruleForm.metadata = {};
	ruleForm.categoryPath = '';
	if (!categoryId) return;

	// 从分类树中查找选中节点，获取path
	const node = findCategoryNode(categoryOptions.value, categoryId);
	if (node?.path !== undefined) {
		ruleForm.categoryPath = node.path;
	}

	getCategory(categoryId)
		.then((res: any) => {
			const data = res.data;
			// 如果接口返回了path，优先使用接口返回的
			if (data?.path !== undefined) {
				ruleForm.categoryPath = data.path;
			}
			if (data?.attrs && Array.isArray(data.attrs)) {
				categoryAttrs.value = data.attrs;
				// 初始化属性值，确保 boolean 类型默认为 false
				categoryAttrs.value.forEach((attr: CategoryAttr) => {
					const key = getAttrKey(attr);
					if (attr.type === 'boolean') {
						ruleForm.metadata[key] = false;
					}
				});
			}
		})
		.catch(() => {
			categoryAttrs.value = [];
		});
};

// 打开弹窗
const openDialog = (row?: any, edit?: boolean) => {
	resetForm();
	isEdit.value = edit || false;
	fetchCategories();

	if (row && edit) {
		// 修改模式：获取详情
		formLoading.value = true;
		getAsset(row.id)
			.then((res: any) => {
				const data = res.data;
				// 支持 fileAddressPrefix 和 imgAddressPrefix
				fileAddressPrefix.value = data.fileAddressPrefix || data.imgAddressPrefix || '';
				ruleForm.id = data.id || '';
				ruleForm.name = data.name || '';
				ruleForm.type = data.type || 'physical';
				ruleForm.categoryId = data.categoryId || '';
				ruleForm.categoryPath = data.categoryPath || '';
				ruleForm.description = data.description || '';
				ruleForm.onlineTime = data.onlineTime || '';
				ruleForm.offlineTime = data.offlineTime || '';
				ruleForm.unlimitedStock = data.unlimitedStock || false;
				ruleForm.stockMode = data.stockMode || 1;

				// 主图预览 (支持 imageUrl 和 fileURL)
				const mainImg = data.imageUrl || data.fileURL;
				if (mainImg) {
					mainImagePreview.value = formatImageUrl(mainImg);
					ruleForm.mainImage = mainImg;
				}

				// 图片列表
				if (data.images && Array.isArray(data.images)) {
					imageFileList.value = data.images.map((url: string, index: number) => ({
						name: `image-${index}`,
						url: formatImageUrl(url),
						response: url, // 存储原始相对路径，供提交时使用
					}));
				}

				// 根据类型加载配置
				if (data.type === 'physical' && data.physicalAssetConfig) {
					Object.assign(ruleForm.physicalAssetConfig, data.physicalAssetConfig);
				}
				if (data.type === 'virtual' && data.virtualAssetConfig) {
					// 先处理 headers 和 params 为数组格式，再赋值
					const config = { ...data.virtualAssetConfig };

					// 确保 apiConfig 存在
					if (!config.apiConfig) {
						config.apiConfig = {
							method: 'GET',
							requestURL: '',
							headers: [],
							params: [],
							authType: 'none',
							authConfig: '',
						};
					} else {
						// 处理 headers
						if (config.apiConfig.headers && typeof config.apiConfig.headers === 'object' && !Array.isArray(config.apiConfig.headers)) {
							config.apiConfig.headers = Object.keys(config.apiConfig.headers).map((key) => ({ key, value: config.apiConfig.headers[key] }));
						} else if (!Array.isArray(config.apiConfig.headers)) {
							config.apiConfig.headers = [];
						}

						// 处理 params
						if (config.apiConfig.params && typeof config.apiConfig.params === 'object' && !Array.isArray(config.apiConfig.params)) {
							config.apiConfig.params = Object.keys(config.apiConfig.params).map((key) => ({ key, value: config.apiConfig.params[key] }));
						} else if (!Array.isArray(config.apiConfig.params)) {
							config.apiConfig.params = [];
						}
					}

					Object.assign(ruleForm.virtualAssetConfig, config);
				}
				if (data.type === 'service' && data.serviceAssetConfig) {
					Object.assign(ruleForm.serviceAssetConfig, data.serviceAssetConfig);
					// 确保 serviceAssetArrivalConfig 对象存在
					if (!ruleForm.serviceAssetConfig.serviceAssetArrivalConfig) {
						ruleForm.serviceAssetConfig.serviceAssetArrivalConfig = {
							schedule: { timeSlots: [], exceptions: [] },
							booking: { minAdvance: 60, minDuration: 30, cancelWindow: 30 },
							capacity: { maxUsers: 0 },
						};
					}
					// 确保 schedule 对象存在
					if (!ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule) {
						ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule = { timeSlots: [], exceptions: [] };
					}
					// 确保数组存在，防止后端返回 null 或 undefined 导致 push 报错
					if (!ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.exceptions) {
						ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.exceptions = [];
					} else {
						// 补充缺失的 exceptionType
						ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.exceptions.forEach((exc: Exception) => {
							if (!exc.exceptionType) {
								if (exc.date) {
									exc.exceptionType = 'date';
								} else if (exc.dayOfWeek) {
									exc.exceptionType = 'dayOfWeek';
								} else {
									// 默认值
									exc.exceptionType = 'date';
								}
							}
						});
					}
					if (!ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots) {
						ruleForm.serviceAssetConfig.serviceAssetArrivalConfig.schedule.timeSlots = [];
					}
				}

				// 元数据
				if (data.metadata) {
					if (Array.isArray(data.metadata)) {
						data.metadata.forEach((item: any) => {
							if (item.name) {
								let val = item.value;
								// 修复回显问题：如果 value 不存在但 options 存在，尝试从 options 恢复值
								if ((val === undefined || val === null) && item.options && item.options.length > 0) {
									if (item.type === 'multi_select') {
										val = item.options.map((opt: any) => opt.value);
									} else if (item.type === 'select') {
										val = item.options[0].value;
									}
								}
								ruleForm.metadata[item.name] = val;
							}
						});
					} else {
						Object.assign(ruleForm.metadata, data.metadata);
					}
				}

				// 加载分类属性
				if (data.categoryId) {
					getCategory(data.categoryId)
						.then((catRes: any) => {
							const catData = catRes.data;
							if (catData?.attrs && Array.isArray(catData.attrs)) {
								categoryAttrs.value = catData.attrs;
								// 初始化属性值，确保 boolean 类型默认为 false
								categoryAttrs.value.forEach((attr: CategoryAttr) => {
									const key = getAttrKey(attr);
									if (attr.type === 'boolean' && ruleForm.metadata[key] === undefined) {
										ruleForm.metadata[key] = false;
									}
								});
							}
						})
						.catch(() => {
							categoryAttrs.value = [];
						})
						.finally(() => {
							// 分类属性加载完成后，保存原始数据用于最小化传参
							buildRequestBody().then((originalBody) => {
								assetFormDiff.saveOriginal(JSON.parse(JSON.stringify(originalBody)));
							});
						});
				} else {
					// 没有分类属性，直接保存原始数据
					buildRequestBody().then((originalBody) => {
						assetFormDiff.saveOriginal(JSON.parse(JSON.stringify(originalBody)));
					});
				}
			})
			.finally(() => {
				formLoading.value = false;
			});
	}

	isShowDialog.value = true;
};

// 关闭弹窗
const closeDialog = () => {
	isShowDialog.value = false;
};

// 取消
const onCancel = () => {
	closeDialog();
};

// 上传图片并返回URL
const uploadImage = async (file: File): Promise<string> => {
	const res: any = await uploadAssetImage(file);

	// 1. 尝试获取并设置 fileAddressPrefix
	// 优先检查顶层，再检查 data 内部
	if (res.fileAddressPrefix) {
		fileAddressPrefix.value = res.fileAddressPrefix;
	} else if (res.data && typeof res.data === 'object' && res.data.fileAddressPrefix) {
		fileAddressPrefix.value = res.data.fileAddressPrefix;
	}

	// 2. 尝试获取 fileURL / url
	// 优先检查顶层 fileURL
	if (res.fileURL) return res.fileURL;

	// 检查 data 对象中的 fileURL 或 url
	if (res.data && typeof res.data === 'object') {
		if (res.data.fileURL) return res.data.fileURL;
		if (res.data.url) return res.data.url;
	}

	// 3. 兼容旧逻辑 (data 直接是 url 字符串)
	if (typeof res.data === 'string') return res.data;

	return '';
};

// 构建请求体
const buildRequestBody = async (): Promise<any> => {
	const body: any = {
		name: ruleForm.name,
		type: ruleForm.type,
		categoryId: ruleForm.categoryId,
		categoryPath: ruleForm.categoryPath || '',
		description: ruleForm.description || '',
	};

	// 编辑模式添加 id
	if (isEdit.value && ruleForm.id) {
		body.id = ruleForm.id;
	}

	// 上下线时间
	if (ruleForm.onlineTime) {
		body.onlineTime = ruleForm.onlineTime;
	}
	if (ruleForm.offlineTime) {
		body.offlineTime = ruleForm.offlineTime;
	}

	// 库存类型
	body.unlimitedStock = ruleForm.unlimitedStock;

	// 库存存储模式（仅租户ID为1时提交）
	if (tenantId.value == 1) {
		body.stockMode = ruleForm.stockMode;
	}

	// 主图 (已在上传时直接赋值给 ruleForm.mainImage)
	if (ruleForm.mainImage) {
		body.imageURL = ruleForm.mainImage;
	}

	// 图片列表
	const imageUrls: string[] = [];
	for (const file of imageFileList.value) {
		let url = (file.response as string) || '';
		if (!url && file.url && !file.url.startsWith('blob:')) {
			url = file.url;
		}
		if (url) {
			// 移除前缀，确保提交相对路径
			if (fileAddressPrefix.value && url.startsWith(fileAddressPrefix.value)) {
				url = url.substring(fileAddressPrefix.value.length);
			}
			imageUrls.push(url);
		}
	}
	body.images = imageUrls;

	// 根据类型添加配置
	if (ruleForm.type === 'physical') {
		body.physicalAssetConfig = ruleForm.physicalAssetConfig;
	} else if (ruleForm.type === 'virtual') {
		// 深拷贝 virtualAssetConfig 以避免修改原对象
		const virtualConfig = JSON.parse(JSON.stringify(ruleForm.virtualAssetConfig));

		// 将数组转换为对象
		if (virtualConfig.apiConfig) {
			if (Array.isArray(virtualConfig.apiConfig.headers)) {
				const headersObj: Record<string, string> = {};
				virtualConfig.apiConfig.headers.forEach((item: KeyValuePair) => {
					if (item.key) headersObj[item.key] = item.value;
				});
				virtualConfig.apiConfig.headers = headersObj;
			}

			if (Array.isArray(virtualConfig.apiConfig.params)) {
				const paramsObj: Record<string, string> = {};
				virtualConfig.apiConfig.params.forEach((item: KeyValuePair) => {
					if (item.key) paramsObj[item.key] = item.value;
				});
				virtualConfig.apiConfig.params = paramsObj;
			}
		}

		body.virtualAssetConfig = virtualConfig;
	} else if (ruleForm.type === 'service') {
		body.serviceAssetConfig = ruleForm.serviceAssetConfig;
	}

	// 元数据（分类属性值）
	if (categoryAttrs.value.length > 0) {
		const metadataArray: any[] = [];
		for (const attr of categoryAttrs.value) {
			const key = getAttrKey(attr);
			let value = ruleForm.metadata[key];

			// 如果是图片类型，且值是 blob 开头（未上传成功的情况），置为空
			if (attr.type === 'image' && typeof value === 'string' && value.startsWith('blob:')) {
				value = '';
			}

			const metaItem: any = {
				name: attr.name,
				type: attr.type,
				value: value,
				...(attr.dictType ? { dictType: attr.dictType } : {}),
			};

			// 只有单选和多选类型才传递 options，且只传递选中的值对应的选项
			if ((attr.type === 'select' || attr.type === 'multi_select') && attr.options && value) {
				const selectedValues = Array.isArray(value) ? value : [value];
				metaItem.options = attr.options.filter((opt: { label: string; value: string }) => selectedValues.includes(opt.value));
			}

			metadataArray.push(metaItem);
		}
		body.metadata = metadataArray;
	}

	return body;
};

// 提交
const onSubmit = async () => {
	const form = formRef.value;
	if (!form) return;

	form.validate(async (valid: boolean) => {
		if (valid) {
			submitLoading.value = true;
			try {
				const fullRequestBody = await buildRequestBody();

				let requestBody: any;
				if (isEdit.value) {
					// 编辑模式：通过 _originalData 让拦截器自动处理最小化传参
					const originalData = assetFormDiff.getOriginal();
					requestBody = {
						...fullRequestBody,
						_originalData: originalData,
					};
				} else {
					// 新增模式：传递所有字段
					requestBody = fullRequestBody;
				}

				const request = isEdit.value ? updateAsset(requestBody) : createAsset(requestBody);

				await request;
				ElMessage.success(isEdit.value ? '修改成功' : '添加成功');
				closeDialog();
				emit('getAssetList');
			} catch (error) {
				ElMessage.error('提交失败');
			} finally {
				submitLoading.value = false;
			}
		}
	});
};

// 暴露方法
defineExpose({
	openDialog,
});
</script>

<style scoped lang="scss">
.w100 {
	width: 100%;
}

.ml10 {
	margin-left: 10px;
}

.mx5 {
	margin: 0 5px;
}

.text-muted {
	color: #909399;
	font-size: 12px;
}

.avatar-uploader {
	:deep(.el-upload) {
		border: 1px dashed var(--el-border-color);
		border-radius: 6px;
		cursor: pointer;
		position: relative;
		overflow: hidden;
		transition: var(--el-transition-duration-fast);

		&:hover {
			border-color: var(--el-color-primary);
		}
	}
}

.avatar-uploader-icon {
	font-size: 28px;
	color: #8c939d;
	width: 100px;
	height: 100px;
	text-align: center;
	line-height: 100px;
}

.avatar {
	width: 100px;
	height: 100px;
	display: block;
	object-fit: cover;
}

.config-list-container {
	width: 100%;

	.config-list-item {
		display: flex;
		align-items: center;
		gap: 8px;
		margin-bottom: 10px;
		flex-wrap: wrap;

		.separator {
			color: #909399;
		}

		.el-button.is-circle {
			:deep(.el-icon) {
				margin-right: 0 !important;
			}
		}
	}
}

.unit-text {
	margin-left: 8px;
	color: #909399;
	font-size: 12px;
	white-space: nowrap;
}

.editor-wrapper {
	width: 100%;
	border: 1px solid #dcdfe6;
	border-radius: 4px;

	:deep(.editor-toolbar) {
		border-bottom: 1px solid #dcdfe6;
	}
}

.attr-image-uploader {
	:deep(.el-upload) {
		border: 1px dashed var(--el-border-color);
		border-radius: 6px;
		cursor: pointer;
	}
}
</style>
