<template>
	<view :class="pageMode ? 'hazard-form-page' : 'popup-content'">
		<view v-if="!pageMode" class="popup-header">
			<view class="popup-title text-bold">{{ title }}</view>
			<view class="popup-close" @click="handleClose">×</view>
		</view>
		<scroll-view :class="pageMode ? 'page-body' : 'popup-body'" scroll-y :style="bodyStyle">
				<view
					v-if="showDraftBanner"
					class="draft-banner"
				>
					<view class="draft-banner-left">
						<text class="cuIcon-info draft-banner-icon"></text>
						<text>已自动恢复您上次未提交的内容</text>
					</view>
					<text class="draft-banner-action" @click="emit('clear-draft')">清空草稿</text>
				</view>

				<view class="flex margin-bottom">
					<view class="text-gray">检查形式</view>
					<view class="text-red">*</view>
				</view>
				<scroll-view class="hazard-choose-scroll" scroll-x :show-scrollbar="false">
					<view class="hazard-choose-row">
						<view
							v-for="(item, index) in SOURCE_OPTIONS"
							:key="item.id"
							class="hazard-choose-tag hazard-choose-tag--source"
							:class="{ 'hazard-choose-tag--active': formData.source === index }"
							@tap.stop="onChooseSelect('source', index)"
						>
							<text class="hazard-choose-tag__text">{{ item.title }}</text>
						</view>
					</view>
				</scroll-view>

				<view class="flex margin-bottom margin-top">
					<view class="text-gray">隐患来源</view>
					<view class="text-red">*</view>
				</view>
				<view class="select-trigger" @click="openHazardSourcePicker">
					<view class="select-value" :class="{ placeholder: !formData.hazardSourceName }">
						{{ formData.hazardSourceName || '请选择隐患来源' }}
					</view>
					<text class="cuIcon-unfold"></text>
				</view>

				<view class="flex margin-bottom margin-top">
					<view class="text-gray">隐患图片</view>
					<view class="text-red">*</view>
				</view>
				<up-upload
					:fileList="fileList"
					@afterRead="afterRead"
					@delete="deletePic"
					name="1"
					multiple
					imageMode="aspectFill"
					:maxCount="10"
				></up-upload>
				<canvas
					:canvas-id="canvasId"
					:width="canvasWidth"
					:height="canvasHeight"
					:style="{
						width: canvasWidth + 'px',
						height: canvasHeight + 'px',
						position: 'fixed',
						left: '-9999px',
						top: '-9999px'
					}"
				></canvas>
				<view class="text-gray text-sm">必填：请上传现场照片作为隐患证据</view>
				<view class="ai-btn-wrapper margin-top">
					<button class="ai-analyze-btn" :loading="aiAnalyzing" :disabled="aiAnalyzing" @click="handleAiAnalyze">
						<text v-if="!aiAnalyzing" class="cuIcon-magic ai-btn-icon"></text>
						{{ aiAnalyzing ? 'AI识别中...' : 'AI 识别隐患' }}
					</button>
				</view>

				<view class="flex margin-bottom margin-top">
					<view class="text-gray">隐患标题</view>
					<view class="text-red">*</view>
				</view>
				<up-input placeholder="请输入内容" border="surround" v-model="formData.title"></up-input>
				<view class="text-sm text-gray margin-top-xs">请用简洁的语言概括隐患要点</view>

				<view class="flex margin-bottom margin-top">
					<view class="text-gray">隐患等级</view>
					<view class="text-red">*</view>
				</view>
				<scroll-view class="hazard-choose-scroll" scroll-x :show-scrollbar="false">
					<view class="hazard-choose-row">
						<view
							v-for="(item, index) in LEVEL_OPTIONS"
							:key="item.id"
							class="hazard-choose-tag hazard-choose-tag--level"
							:class="{ 'hazard-choose-tag--active': formData.level === index }"
							@tap.stop="onChooseSelect('level', index)"
						>
							<text class="hazard-choose-tag__text">{{ item.title }}</text>
						</view>
					</view>
				</scroll-view>

				<view class="flex margin-bottom margin-top">
					<view class="text-gray">隐患位置</view>
					<view class="text-red">*</view>
				</view>
				<view class="address-box">
					<up-input
						:key="'address-' + formRenderKey"
						class="address-input-wrapper"
						v-model="address"
						placeholder="请输入地址"
						border="surround"
					></up-input>
					<button class="btn-address bg-blue" @tap.stop="chooseLocation">选择地址</button>
				</view>
				<view class="text-gray text-sm margin-top-xs">如：办公楼3层东侧消防通道、生产车间A区设备旁等，或点击"选择地址"按钮在地图上选择</view>

				<view class="flex margin-bottom margin-top">
					<view class="text-gray">法律依据</view>
				</view>
				<view class="select-trigger" @click="openLawPopup">
					<view class="select-value" :class="{ placeholder: !formData.regulationName }">
						{{ formData.regulationName || '请选择法律依据' }}
					</view>
					<text class="cuIcon-unfold"></text>
				</view>

				<view class="flex margin-bottom margin-top">
					<view class="text-gray">隐患区域</view>
				</view>
				<view class="select-trigger" @click="openAreaPicker">
					<view class="select-value" :class="{ placeholder: !areaName }">
						{{ areaName || '请选择隐患区域' }}
					</view>
					<text class="cuIcon-unfold"></text>
				</view>

				<view class="flex margin-bottom margin-top">
					<view class="text-gray">隐患描述</view>
					<view class="text-red">*</view>
				</view>
				<up-textarea
					:key="'description-' + formRenderKey"
					v-model="formData.description"
					placeholder="请输入内容"
				></up-textarea>
				<view class="text-gray text-sm margin-top-xs">请详细说明隐患现状、潜在风险及影响范围</view>

				<view class="text-gray margin-bottom margin-top">隐患标签</view>
				<view class="hazard-choose-wrap">
					<view
						v-for="(item, index) in tagOptions"
						:key="item.id"
						class="hazard-choose-tag hazard-choose-tag--tag"
						:class="{ 'hazard-choose-tag--active': formData.tagIndex === index }"
						@tap.stop="onChooseSelect('tagIndex', index)"
					>
						<text class="hazard-choose-tag__text">{{ item.title }}</text>
					</view>
				</view>

				<view class="flex margin-bottom margin-top">
					<view class="text-gray">下一步流程</view>
					<view class="text-red">*</view>
				</view>
				<view class="static-field">隐患交办</view>

				<view class="flex margin-bottom margin-top">
					<view class="text-gray">下一步处理人</view>
					<view class="text-red">*</view>
				</view>
				<view class="static-field">部门、企业管理员、企业成员</view>
			</scroll-view>
		<view :class="pageMode ? 'page-footer' : 'popup-footer'">
			<button class="btn-cancel" @click="handleClose">取消</button>
			<button class="btn-confirm bg-blue" :loading="submitting" @click="handleConfirm">提交</button>
		</view>
	</view>

	<!-- 选择法规弹出框 -->
	<u-popup :show="showLawPopup" mode="center" round="20" :safe-area-inset-bottom="false" @close="showLawPopup = false">
		<view class="law-popup">
			<view class="popup-header">
				<view class="popup-title">选择法律依据</view>
				<view class="popup-close" @click="showLawPopup = false">×</view>
			</view>

			<view class="search-box">
				<text class="cuIcon-search search-icon"></text>
				<input class="search-input" v-model="lawKeyword" placeholder="请输入关键词搜索" @confirm="searchRegulation" />
				<text class="search-btn" @click="searchRegulation">搜索</text>
			</view>

			<scroll-view class="law-list" scroll-y @scrolltolower="loadMoreLaw">
				<view v-if="lawLoading && lawList.length === 0" class="loading-tip">加载中...</view>
				<view v-else-if="!lawLoading && lawList.length === 0" class="empty-tip">暂无数据</view>
				<template v-else>
					<view
						class="law-item"
						:class="{ 'law-item-active': selectedLawId === item.id }"
						v-for="item in lawList"
						:key="item.id"
						@click="selectLaw(item)"
					>
						<view class="law-title">{{ item.depict }}</view>
						<view class="law-basis text-gray">{{ item.legalBasis }}</view>
					</view>
					<view v-if="lawLoading" class="loading-tip">加载中...</view>
				</template>
			</scroll-view>

			<view class="law-popup-footer">
				<button class="btn-cancel" @click="showLawPopup = false">取消</button>
				<button class="btn-confirm bg-blue" @click="confirmLaw">确定</button>
			</view>
		</view>
	</u-popup>

	<!-- 隐患来源选择弹窗 -->
	<u-popup :show="showHazardSourcePicker" mode="bottom" round="20" @close="showHazardSourcePicker = false">
		<view class="picker-popup">
			<view class="picker-header">
				<view class="picker-cancel" @click="showHazardSourcePicker = false">取消</view>
				<view class="picker-title">选择隐患来源</view>
				<view class="picker-confirm" @click="confirmHazardSourceSelect">确定</view>
			</view>
			<scroll-view class="picker-body" scroll-y>
				<view
					v-for="item in hazardSourceList"
					:key="item.code"
					class="picker-item"
					:class="{ 'picker-item-active': tempHazardSourceCode === item.code }"
					@click="tempHazardSourceCode = item.code"
				>
					<text>{{ item.name }}</text>
					<text v-if="tempHazardSourceCode === item.code" class="cuIcon-check text-blue"></text>
				</view>
				<view v-if="hazardSourceList.length === 0" class="text-gray text-center padding">暂无隐患来源数据</view>
			</scroll-view>
		</view>
	</u-popup>

	<!-- 区域选择弹窗 -->
	<u-popup :show="showAreaPicker" mode="bottom" round="20" @close="showAreaPicker = false">
		<view class="picker-popup">
			<view class="picker-header">
				<view class="picker-cancel" @click="showAreaPicker = false">取消</view>
				<view class="picker-title">选择隐患区域</view>
				<view class="picker-confirm" @click="confirmAreaSelect">确定</view>
			</view>
			<scroll-view class="picker-body" scroll-y>
				<view
					v-for="item in areaList"
					:key="item.id"
					class="picker-item"
					:class="{ 'picker-item-active': tempAreaId === item.id }"
					@click="tempAreaId = item.id"
				>
					<view class="flex align-center">
						<view class="area-color-dot" :style="{ backgroundColor: item.color }"></view>
						<text>{{ item.name }}</text>
					</view>
					<text v-if="tempAreaId === item.id" class="cuIcon-check text-blue"></text>
				</view>
				<view v-if="areaList.length === 0" class="text-gray text-center padding">暂无区域数据</view>
			</scroll-view>
		</view>
	</u-popup>
</template>

<script setup>
import { ref, reactive, computed, watch, getCurrentInstance, nextTick } from 'vue';
import { addHiddenDanger, getHiddenDangerLabelList, getHazardSourceList, getRegulationList, analyzeHazardImage } from '@/request/api.js';
import { getAreaList } from '@/request/three_one_api/area.js';
import { createUploadListHandlers } from '@/utils/upload.js';
import {
	LEVEL_OPTIONS,
	SOURCE_OPTIONS,
	AI_LEVEL_MAP,
	createEmptyHazardPayload,
	buildHiddenDangerParams
} from './hazardForm.js';

const props = defineProps({
	pageMode: {
		type: Boolean,
		default: false
	},
	show: {
		type: Boolean,
		default: false
	},
	title: {
		type: String,
		default: '填写隐患信息'
	},
	mode: {
		type: String,
		default: 'collect'
	},
	modelValue: {
		type: Object,
		default: null
	},
	extraParams: {
		type: Object,
		default: () => ({})
	},
	showDraftBanner: {
		type: Boolean,
		default: false
	},
	bodyHeight: {
		type: String,
		default: ''
	},
	canvasId: {
		type: String,
		default: 'hazardFormWatermarkCanvas'
	}
});

const emit = defineEmits(['update:show', 'update:modelValue', 'success', 'confirm', 'clear-draft', 'close', 'draft-change']);

const popupVisible = computed({
	get: () => props.pageMode ? true : props.show,
	set: (value) => {
		if (!props.pageMode) {
			emit('update:show', value);
		}
	}
});

const isApiSuccess = (res) => Number(res?.code) === 0 || Number(res?.code) === 200;

const bodyStyle = computed(() => {
	if (props.bodyHeight) {
		return { height: props.bodyHeight };
	}
	if (props.pageMode) {
		return { maxHeight: 'none' };
	}
	return {};
});

const canvasWidth = ref(300);
const canvasHeight = ref(300);
const submitting = ref(false);
const aiAnalyzing = ref(false);
const syncingFromParent = ref(false);

const formData = reactive({
	title: '',
	level: 0,
	source: 0,
	hazardSourceCode: null,
	hazardSourceName: '',
	description: '',
	tagIndex: 0,
	tagId: null,
	regulationId: null,
	regulationName: ''
});
const address = ref('');
const lng = ref(0);
const lat = ref(0);
const areaId = ref('');
const areaName = ref('');
const fileList = ref([]);
const tagOptions = ref([]);

const showLawPopup = ref(false);
const lawKeyword = ref('');
const selectedLawId = ref(null);
const selectedLawName = ref('');
const lawList = ref([]);
const lawLoading = ref(false);
const lawPageNum = ref(1);
const lawPageSize = ref(10);
const hasMoreLaw = ref(true);

const showHazardSourcePicker = ref(false);
const hazardSourceList = ref([]);
const tempHazardSourceCode = ref(null);

const showAreaPicker = ref(false);
const areaList = ref([]);
const tempAreaId = ref('');
const choosingLocation = ref(false);
const suppressModelEmit = ref(false);
const formRenderKey = ref(0);

const LOCATION_PICKER_DRAFT_KEY = 'hazard_form_location_picker_draft';

const uploadInstance = getCurrentInstance();
const { afterRead, deletePic } = createUploadListHandlers(fileList, {
	watermark: {
		canvasId: props.canvasId,
		canvasWidthRef: canvasWidth,
		canvasHeightRef: canvasHeight,
		instance: uploadInstance
	}
});

function getPayload() {
	syncTagIdFromIndex();
	return {
		formData: {
			title: formData.title,
			level: formData.level,
			source: formData.source,
			hazardSourceCode: formData.hazardSourceCode,
			hazardSourceName: formData.hazardSourceName,
			description: formData.description,
			tagIndex: formData.tagIndex,
			tagId: formData.tagId,
			regulationId: formData.regulationId,
			regulationName: formData.regulationName
		},
		address: address.value,
		lng: lng.value,
		lat: lat.value,
		areaId: areaId.value,
		areaName: areaName.value,
		fileList: fileList.value,
		tagOptions: tagOptions.value
	};
}

function applyPayload(payload) {
	if (!payload) return;
	syncingFromParent.value = true;
	const data = payload.formData || {};
	formData.title = data.title || '';
	formData.level = data.level ?? 0;
	formData.source = data.source ?? 0;
	formData.hazardSourceCode = data.hazardSourceCode ?? null;
	formData.hazardSourceName = data.hazardSourceName || '';
	syncHazardSourceNameFromCode();
	formData.description = data.description || '';
	formData.tagIndex = data.tagIndex ?? 0;
	formData.tagId = data.tagId ?? null;
	formData.regulationId = data.regulationId ?? null;
	formData.regulationName = data.regulationName || '';
	address.value = payload.address || '';
	lng.value = payload.lng || 0;
	lat.value = payload.lat || 0;
	areaId.value = payload.areaId || '';
	areaName.value = payload.areaName || '';
	fileList.value = payload.fileList ? [...payload.fileList] : [];
	selectedLawId.value = data.regulationId ?? null;
	selectedLawName.value = data.regulationName || '';
	syncingFromParent.value = false;
	formRenderKey.value++;
}

function hasPayloadContent(payload) {
	if (!payload) return false;
	const data = payload.formData || {};
	const files = payload.fileList || [];
	return !!(
		data.title ||
		data.description ||
		data.regulationName ||
		payload.address ||
		(files.length > 0)
	);
}

function getLocationPickerDraftKey() {
	return props.extraParams?.locationDraftKey || LOCATION_PICKER_DRAFT_KEY;
}

function saveLocationPickerDraft() {
	const snapshot = getPayload();
	try {
		uni.setStorageSync(getLocationPickerDraftKey(), snapshot);
	} catch (error) {
		console.error('保存选点草稿失败:', error);
	}
	return snapshot;
}

function loadLocationPickerDraft() {
	try {
		const draft = uni.getStorageSync(getLocationPickerDraftKey());
		return draft && typeof draft === 'object' ? draft : null;
	} catch (error) {
		return null;
	}
}

function clearLocationPickerDraft() {
	try {
		uni.removeStorageSync(getLocationPickerDraftKey());
	} catch (error) {
		console.error('清除选点草稿失败:', error);
	}
}

function restoreAfterLocationPicker(patch = {}) {
	const draft = loadLocationPickerDraft();
	if (!draft) return false;

	applyPayload({
		...draft,
		...patch,
		formData: {
			...(draft.formData || {}),
			...(patch.formData || {})
		},
		fileList: patch.fileList ?? draft.fileList ?? []
	});
	clearLocationPickerDraft();
	return true;
}

function reopenPopupAfterLocation() {
	nextTick(() => {
		choosingLocation.value = false;
		if (!props.pageMode) {
			popupVisible.value = true;
		}
		emitModelValue();
	});
}

function resetForm() {
	applyPayload(createEmptyHazardPayload());
	selectedLawId.value = null;
	selectedLawName.value = '';
	tempAreaId.value = '';
	clearLocationPickerDraft();
}

function syncTagIdFromIndex() {
	const selectedTag = tagOptions.value[formData.tagIndex];
	formData.tagId = selectedTag?.id ?? formData.tagId ?? null;
}

function onChooseSelect(field, index) {
	formData[field] = Number(index);
	if (field === 'tagIndex') {
		syncTagIdFromIndex();
	}
	emitModelValue();
}

function emitModelValue() {
	if (suppressModelEmit.value || syncingFromParent.value) return;
	if (props.pageMode && props.mode === 'direct') {
		emit('draft-change', getPayload());
		return;
	}
	if (props.modelValue === null) return;
	// collect / direct 弹窗模式不与父组件 v-model 双向同步
	if (props.mode === 'collect' || props.mode === 'direct') return;
	emit('update:modelValue', getPayload());
}

function closePopup() {
	if (props.pageMode) return;
	popupVisible.value = false;
}

function handleClose() {
	if (props.pageMode) {
		uni.navigateBack();
		return;
	}
	closePopup();
	emit('close');
}

function validateForm() {
	if (fileList.value.length === 0) {
		uni.showToast({ title: '请上传隐患图片', icon: 'none' });
		return false;
	}
	if (!formData.title) {
		uni.showToast({ title: '请输入隐患标题', icon: 'none' });
		return false;
	}
	if (formData.hazardSourceCode == null) {
		uni.showToast({ title: '请选择隐患来源', icon: 'none' });
		return false;
	}
	if (!address.value) {
		uni.showToast({ title: '请输入隐患位置', icon: 'none' });
		return false;
	}
	if (!formData.description) {
		uni.showToast({ title: '请输入隐患描述', icon: 'none' });
		return false;
	}
	return true;
}

async function handleConfirm() {
	if (!validateForm()) return;

	const payload = getPayload();

	if (props.mode === 'collect') {
		// 先回写数据再关弹窗，避免父组件在 show=false 时提前清空索引导致 confirm 丢失
		if (props.modelValue !== null) {
			emit('update:modelValue', payload);
		}
		emit('confirm', payload);
		closePopup();
		uni.showToast({ title: '隐患信息已暂存', icon: 'success' });
		return;
	}

	submitting.value = true;
	try {
		const params = buildHiddenDangerParams(payload, props.extraParams);
		const res = await addHiddenDanger(params);
		if (isApiSuccess(res)) {
			suppressModelEmit.value = true;
			if (!props.pageMode) {
				closePopup();
			}
			emit('success', { ...payload, hazardId: res.data });
			await nextTick();
			resetForm();
			uni.showToast({ title: res.msg || '新增成功', icon: 'success' });
			if (props.pageMode) {
				setTimeout(() => {
					uni.navigateBack();
				}, 1500);
			}
		} else {
			uni.showToast({ title: res.msg || '新增失败', icon: 'none' });
		}
	} catch (error) {
		console.error(error);
		uni.showToast({ title: '请求失败', icon: 'none' });
	} finally {
		suppressModelEmit.value = false;
		submitting.value = false;
	}
}

function openLawPopup() {
	showLawPopup.value = true;
	if (lawList.value.length === 0) {
		fetchRegulationList();
	}
}

async function fetchRegulationList(isLoadMore = false) {
	if (lawLoading.value) return;
	lawLoading.value = true;
	try {
		const params = {
			pageNum: lawPageNum.value,
			pageSize: lawPageSize.value,
			status: 1
		};
		if (lawKeyword.value?.trim()) {
			params.keyword = lawKeyword.value.trim();
		}
		const res = await getRegulationList(params);
		if (res.code === 0) {
			const records = res.data.records || res.data || [];
			lawList.value = isLoadMore ? [...lawList.value, ...records] : records;
			const total = res.data.total || 0;
			hasMoreLaw.value = lawList.value.length < total;
		}
	} catch (error) {
		console.error('获取法规列表失败:', error);
	} finally {
		lawLoading.value = false;
	}
}

function searchRegulation() {
	lawPageNum.value = 1;
	lawList.value = [];
	hasMoreLaw.value = true;
	fetchRegulationList();
}

function loadMoreLaw() {
	if (!hasMoreLaw.value || lawLoading.value) return;
	lawPageNum.value++;
	fetchRegulationList(true);
}

function selectLaw(item) {
	selectedLawId.value = item.id;
	selectedLawName.value = item.depict || item.keyword || '';
}

function confirmLaw() {
	if (selectedLawId.value) {
		formData.regulationId = selectedLawId.value;
		formData.regulationName = selectedLawName.value;
	}
	showLawPopup.value = false;
	emitModelValue();
}

function syncHazardSourceNameFromCode() {
	if (formData.hazardSourceCode == null) return;
	const selected = hazardSourceList.value.find((item) => item.code === formData.hazardSourceCode);
	if (selected) {
		formData.hazardSourceName = selected.name;
	}
}

function openHazardSourcePicker() {
	tempHazardSourceCode.value = formData.hazardSourceCode;
	showHazardSourcePicker.value = true;
}

function confirmHazardSourceSelect() {
	if (tempHazardSourceCode.value != null) {
		const selected = hazardSourceList.value.find((item) => item.code === tempHazardSourceCode.value);
		if (selected) {
			formData.hazardSourceCode = selected.code;
			formData.hazardSourceName = selected.name;
		}
	}
	showHazardSourcePicker.value = false;
	emitModelValue();
}

async function fetchHazardSourceList() {
	try {
		const res = await getHazardSourceList();
		if (isApiSuccess(res)) {
			const list = Array.isArray(res.data) ? res.data : [];
			hazardSourceList.value = list
				.map((item) => ({
					code: item.code,
					name: item.name || ''
				}))
				.filter((item) => item.code != null && item.name);
			syncHazardSourceNameFromCode();
		}
	} catch (error) {
		console.error('获取隐患来源列表失败:', error);
	}
}

function openAreaPicker() {
	tempAreaId.value = areaId.value;
	showAreaPicker.value = true;
}

async function fetchAreaList() {
	try {
		const res = await getAreaList();
		if (res.code === 0 && res.data?.records) {
			areaList.value = res.data.records;
		}
	} catch (error) {
		console.error('获取区域列表失败:', error);
	}
}

function confirmAreaSelect() {
	if (tempAreaId.value) {
		areaId.value = tempAreaId.value;
		const selected = areaList.value.find((item) => item.id === tempAreaId.value);
		areaName.value = selected ? selected.name : '';
	}
	showAreaPicker.value = false;
	emitModelValue();
}

function chooseLocation() {
	choosingLocation.value = true;
	saveLocationPickerDraft();
	if (!props.pageMode) {
		closePopup();
		setTimeout(() => {
			uni.getLocation({
				type: 'gcj02',
				success: (locationRes) => {
					openChooseLocation(locationRes.latitude, locationRes.longitude);
				},
				fail: () => {
					openChooseLocation();
				}
			});
		}, 300);
		return;
	}
	uni.getLocation({
		type: 'gcj02',
		success: (locationRes) => {
			openChooseLocation(locationRes.latitude, locationRes.longitude);
		},
		fail: () => {
			openChooseLocation();
		}
	});
}

function openChooseLocation(latitude, longitude) {
	const options = {};
	if (latitude != null && longitude != null) {
		options.latitude = latitude;
		options.longitude = longitude;
	}
	uni.chooseLocation({
		...options,
		success: (res) => {
			restoreAfterLocationPicker({
				address: res.address + (res.name ? `(${res.name})` : ''),
				lng: res.longitude,
				lat: res.latitude
			});
			reopenPopupAfterLocation();
		},
		fail: (err) => {
			restoreAfterLocationPicker();
			reopenPopupAfterLocation();
			if (err.errMsg && err.errMsg.indexOf('cancel') === -1) {
				uni.showToast({ title: '选择位置失败', icon: 'none' });
			}
		}
	});
}

async function handleAiAnalyze() {
	const imageFiles = fileList.value.filter((f) => {
		return f.status === 'success' && f.url.toLowerCase().match(/\.(jpg|jpeg|png|gif|bmp|webp)$/);
	});
	if (imageFiles.length === 0) {
		uni.showToast({ title: '请先上传隐患图片', icon: 'none' });
		return;
	}

	aiAnalyzing.value = true;
	try {
		const analyzeRes = await analyzeHazardImage({ imageUrl: imageFiles[0].url });
		if (analyzeRes.code === 0 && analyzeRes.data) {
			const aiData = analyzeRes.data;
			if (aiData.title) formData.title = aiData.title;
			if (aiData.description) formData.description = aiData.description;
			if (aiData.level) {
				const levelIndex = AI_LEVEL_MAP[aiData.level];
				if (levelIndex !== undefined) {
					formData.level = levelIndex;
				}
			}
			emitModelValue();
			uni.showToast({ title: 'AI分析完成，已自动填充', icon: 'success', duration: 2000 });
		} else {
			uni.showToast({ title: analyzeRes.msg || 'AI分析失败', icon: 'none' });
		}
	} catch (error) {
		console.error('AI分析接口调用失败:', error);
		uni.showToast({ title: 'AI分析失败，请重试', icon: 'none' });
	} finally {
		aiAnalyzing.value = false;
	}
}

async function fetchTagOptions() {
	try {
		const res = await getHiddenDangerLabelList();
		if (res.code === 0) {
			tagOptions.value = res.data.map((item) => ({
				id: item.id,
				title: item.name
			}));
			syncTagIdFromIndex();
		}
	} catch (error) {
		console.error('获取标签列表失败:', error);
	}
}

watch(
	() => props.modelValue,
	(val) => {
		// direct 页面模式由页面草稿恢复，不与父组件 v-model 双向同步
		if (props.mode === 'direct' && props.pageMode) return;
		if (props.mode === 'direct') return;
		if (hasPayloadContent(val)) {
			applyPayload(val);
		}
	},
	{ deep: true, immediate: true }
);

watch(
	() => ({
		title: formData.title,
		level: formData.level,
		source: formData.source,
		hazardSourceCode: formData.hazardSourceCode,
		hazardSourceName: formData.hazardSourceName,
		description: formData.description,
		tagIndex: formData.tagIndex,
		regulationId: formData.regulationId,
		regulationName: formData.regulationName,
		address: address.value,
		areaId: areaId.value,
		areaName: areaName.value,
		fileListLength: fileList.value.length
	}),
	() => {
		if (!props.pageMode || syncingFromParent.value) return;
		emit('draft-change', getPayload());
	},
	{ deep: true }
);

watch(
	() => props.show,
	(val) => {
		if (props.pageMode) return;
		if (val && hazardSourceList.value.length === 0) {
			fetchHazardSourceList();
		}
		if (val && areaList.value.length === 0) {
			fetchAreaList();
		}
		if (!val) return;

		// 地图选点返回时由选点回调恢复，避免空 modelValue 覆盖已填内容
		if (choosingLocation.value) {
			return;
		}

		const locationDraft = loadLocationPickerDraft();
		if (locationDraft) {
			applyPayload(locationDraft);
			clearLocationPickerDraft();
			return;
		}

		if (hasPayloadContent(props.modelValue)) {
			applyPayload(props.modelValue);
		}
	}
);

fetchTagOptions();
fetchHazardSourceList();
fetchAreaList();

defineExpose({
	getPayload,
	applyPayload,
	resetForm,
	validateForm
});
</script>

<style lang="scss" scoped>
.hazard-form-page {
	min-height: 100vh;
	background: #ebf2fc;
	padding: 24rpx;
	padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
	box-sizing: border-box;
}

.page-body {
	padding: 30rpx;
	max-height: none;
	background: #fff;
	border-radius: 16rpx;
	box-sizing: border-box;
}

.page-footer {
	display: flex;
	gap: 24rpx;
	margin-top: 32rpx;
	padding-bottom: env(safe-area-inset-bottom);

	button {
		flex: 1;
		height: 88rpx;
		line-height: 88rpx;
		border-radius: 44rpx;
		font-size: 30rpx;
		margin: 0;
		padding: 0;

		&::after {
			border: none;
		}
	}

	.btn-cancel {
		background: #fff;
		color: #2667e9;
		border: 2rpx solid #2667e9;
	}

	.btn-confirm {
		color: #fff;
		border: none;
	}
}

.popup-content {
	width: 600rpx;
	background: #fff;
	border-radius: 20rpx;
	overflow: hidden;
}

.popup-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 30rpx;
	border-bottom: 1rpx solid #eee;

	.popup-title {
		font-size: 32rpx;
		color: #333;
	}

	.popup-close {
		font-size: 40rpx;
		color: #999;
		line-height: 1;
	}
}

.popup-body {
	padding: 30rpx;
	max-height: 900rpx;
	overflow-y: auto;
}

.draft-banner {
	font-size: 24rpx;
	background-color: #fff7eb;
	border: 1rpx solid #ffe4cc;
	width: 100%;
	box-sizing: border-box;
	display: flex;
	flex-direction: row;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 20rpx;
	padding: 16rpx 20rpx;
	border-radius: 8rpx;
	color: #fa8c16;
}

.draft-banner-left {
	display: flex;
	flex-direction: row;
	align-items: center;
}

.draft-banner-icon {
	margin-right: 10rpx;
}

.draft-banner-action {
	cursor: pointer;
	padding: 0 10rpx;
	color: #2667e9;
	font-weight: bold;
}

.hazard-choose-scroll {
	width: 100%;
	white-space: nowrap;
}

.hazard-choose-row {
	display: inline-flex;
	flex-direction: row;
	align-items: center;
	padding-right: 20rpx;
}

.hazard-choose-wrap {
	display: flex;
	flex-wrap: wrap;
}

.hazard-choose-tag {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	border: 1rpx solid #dcdfe6;
	border-radius: 8rpx;
	background: #fff;
	flex-shrink: 0;
	margin-right: 12rpx;

	&--source {
		width: 152rpx;
		height: 64rpx;
	}

	&--level {
		width: 183rpx;
		height: 72rpx;
	}

	&--tag {
		min-width: 120rpx;
		height: 64rpx;
		padding: 0 24rpx;
		margin-bottom: 12rpx;
	}

	&--active {
		background: #2667e9;
		border-color: #2667e9;

		.hazard-choose-tag__text {
			color: #fff;
		}
	}

	&__text {
		font-size: 24rpx;
		line-height: 1.2;
		color: #606266;
		text-align: center;
	}
}

.ai-btn-wrapper {
	display: flex;
	justify-content: flex-end;
}

.ai-analyze-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 72rpx;
	padding: 0 32rpx;
	font-size: 28rpx;
	color: #fff;
	background: linear-gradient(135deg, #4facfe 0%, #2668ea 100%);
	border-radius: 36rpx;
	border: none;

	&::after {
		border: none;
	}

	.ai-btn-icon {
		margin-right: 8rpx;
		font-size: 30rpx;
	}

	&[disabled] {
		opacity: 0.7;
	}
}

.popup-footer {
	display: flex;
	border-top: 1rpx solid #eee;

	button {
		flex: 1;
		height: 90rpx;
		line-height: 90rpx;
		border-radius: 0;
		font-size: 30rpx;

		&::after {
			border: none;
		}
	}

	.btn-cancel {
		background: #fff;
		color: #666;
	}

	.btn-confirm {
		color: #fff;
	}
}

.address-box {
	display: flex;
	align-items: center;
	gap: 20rpx;

	.address-input-wrapper {
		flex: 1;
	}

	.btn-address {
		flex-shrink: 0;
		height: 70rpx;
		line-height: 70rpx;
		padding: 0 30rpx;
		font-size: 26rpx;
		border-radius: 8rpx;
		color: #fff;

		&::after {
			border: none;
		}
	}
}

.select-trigger {
	display: flex;
	align-items: center;
	justify-content: space-between;
	background: #fff;
	border: 1rpx solid #dcdfe6;
	border-radius: 8rpx;
	padding: 20rpx 24rpx;

	.select-value {
		flex: 1;
		font-size: 28rpx;
		color: #333;

		&.placeholder {
			color: #c0c4cc;
		}
	}
}

.static-field {
	background: #fff;
	border: 1rpx solid #dcdfe6;
	border-radius: 8rpx;
	padding: 20rpx 24rpx;
	font-size: 28rpx;
	color: #333;
	line-height: 1.5;
}

.picker-popup {
	background: #fff;

	.picker-header {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 30rpx;
		border-bottom: 1rpx solid #eee;

		.picker-cancel {
			font-size: 28rpx;
			color: #999;
		}

		.picker-title {
			font-size: 32rpx;
			font-weight: bold;
			color: #333;
		}

		.picker-confirm {
			font-size: 28rpx;
			color: #2667e9;
		}
	}

	.picker-body {
		max-height: 600rpx;
		padding: 0 30rpx;
	}

	.picker-item {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 30rpx 0;
		border-bottom: 1rpx solid #f5f5f5;
		font-size: 30rpx;
		color: #333;

		&:last-child {
			border-bottom: none;
		}

		&.picker-item-active {
			color: #2667e9;
		}
	}
}

.area-color-dot {
	width: 24rpx;
	height: 24rpx;
	border-radius: 50%;
	margin-right: 16rpx;
}

.law-popup {
	width: 600rpx;
	background: #fff;
	border-radius: 20rpx;
	overflow: hidden;
	max-height: 80vh;

	.popup-header {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 30rpx;
		border-bottom: 1rpx solid #eee;

		.popup-title {
			font-size: 32rpx;
			font-weight: bold;
			color: #333;
		}

		.popup-close {
			font-size: 40rpx;
			color: #999;
		}
	}
}

.search-box {
	display: flex;
	align-items: center;
	background: #f5f5f5;
	border-radius: 40rpx;
	padding: 16rpx 24rpx;
	margin: 20rpx 30rpx;

	.search-icon {
		font-size: 28rpx;
		color: #999;
		margin-right: 12rpx;
	}

	.search-input {
		flex: 1;
		font-size: 28rpx;
		background: transparent;
		border: none;
	}

	.search-btn {
		color: #2667e9;
		font-size: 26rpx;
		margin-left: 16rpx;
	}
}

.loading-tip,
.empty-tip {
	text-align: center;
	padding: 40rpx;
	color: #999;
	font-size: 26rpx;
}

.law-list {
	max-height: 400rpx;
	padding: 0 30rpx;
}

.law-item {
	padding: 24rpx;
	border: 2rpx solid #e5e5e5;
	border-radius: 12rpx;
	margin-bottom: 16rpx;
	font-size: 28rpx;
	color: #333;

	.law-title {
		line-height: 1.5;
		margin-bottom: 8rpx;
		font-weight: bold;
	}

	.law-basis {
		font-size: 24rpx;
		line-height: 1.4;
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}
}

.law-item-active {
	border-color: #2667e9;
	background: #f0f6ff;
}

.law-popup-footer {
	display: flex;
	padding: 30rpx;
	border-top: 1rpx solid #eee;
	gap: 20rpx;

	button {
		flex: 1;
		height: 80rpx;
		line-height: 80rpx;
		font-size: 28rpx;
		border-radius: 40rpx;

		&::after {
			border: none;
		}
	}

	.btn-cancel {
		background: #f5f5f5;
		color: #666;
	}

	.btn-confirm {
		background: #2667e9;
		color: #fff;
	}
}
</style>
