<template>
	<view class="order-detail-page">
		<nav-bar title="订单详情"></nav-bar>
		<!-- 骨架屏 -->
		<view class="skeleton-page" v-if="loading">
			<view class="skeleton-header skeleton-box"></view>
			<view class="skeleton-progress skeleton-box"></view>
			<view class="skeleton-row-cards">
				<view class="skeleton-card skeleton-box"></view>
				<view class="skeleton-card skeleton-box"></view>
			</view>
			<view class="skeleton-content skeleton-box"></view>
		</view>

		<!-- 真实内容 -->
		<view class="real-content fade-in" v-else>
			<!-- 订单号与状态 -->
			<view class="order-header">
				<view class="order-id-row">
					<text class="order-id">{{ order.code || order.id }}</text>
					<text :class="['status-badge', `badge-${order.statusKey}`]">{{ order.statusText }}</text>
					<text class="service-badge">{{ currentServiceName }}</text>
				</view>
			</view>

			<!-- 状态进度条 -->
			<view class="progress-card">
				<view class="progress-steps">
					<view v-for="(step, i) in progressSteps" :key="i"
						:class="['step-item', { done: step.done, active: step.active }]">
						<view class="step-circle">
							<uni-icons v-if="step.done" type="checkmarkempty" size="12" color="#fff"></uni-icons>
							<text v-else class="step-num">{{ i + 1 }}</text>
						</view>
						<view class="step-line" v-if="i < progressSteps.length - 1" :class="{ done: step.done }"></view>
						<text class="step-label">{{ step.label }}</text>
						<text class="step-time">{{ step.time }}</text>
					</view>
				</view>
			</view>

			<!-- 宠物档案 + 用户信息 -->
			<view class="info-row-cards">
				<view class="info-card pet-card">
					<text class="card-label">宠物档案</text>
					<view class="pet-header">
						<view class="pet-avatar">
							<image v-if="order.petAvatarUrl" :src="order.petAvatarUrl" mode="aspectFill"
								class="avatar-img"></image>
							<text v-else>{{ (order.petName || '宠')[0] }}</text>
						</view>
						<view class="pet-basic">
							<text class="pet-name">
								{{ order.petName || '-' }}
								<text class="gender-male" v-if="order.petGender === 'male'">♂</text>
								<text class="gender-female" v-else-if="order.petGender === 'female'">♀</text>
							</text>
							<view class="pet-tags">
								<text class="mini-tag" v-if="order.petAge">{{ order.petAge }}</text>
								<text class="mini-tag" v-if="order.petWeight">{{ order.petWeight }}</text>
								<text class="breed-badge" v-if="order.petBreed">{{ order.petBreed }}</text>
							</view>
						</view>
					</view>
					<view class="pet-attrs">
						<view class="attr-item">
							<text class="attr-label">品种</text>
							<text class="attr-val">{{ order.petBreed || '-' }}</text>
						</view>
						<view class="attr-item">
							<text class="attr-label">疫苗状态</text>
							<text class="attr-val highlight">{{ order.petVaccine || '-' }}</text>
						</view>
						<view class="attr-item full">
							<text class="attr-label">性格特点</text>
							<text class="attr-val">{{ order.petCharacter || '-' }}</text>
						</view>
					</view>
				</view>

				<view class="info-card user-card">
					<text class="card-label">用户信息</text>
					<view class="user-header">
						<view class="user-avatar">
							<image v-if="order.userAvatarUrl" :src="order.userAvatarUrl" mode="aspectFill"
								class="avatar-img"></image>
							<uni-icons v-else type="person" size="26" color="#aaa"></uni-icons>
						</view>
						<view class="user-basic">
							<text class="user-name-text">{{ order.userName }}</text>
							<text class="user-phone">{{ order.userPhone }}</text>
						</view>
					</view>
					<view class="service-address-box">
						<text class="addr-label">服务地址</text>
						<text class="addr-text">{{ order.address }}</text>
					</view>
				</view>
			</view>

			<!-- 标签页 -->
			<view class="detail-tabs-wrap">
				<view class="tab-nav">
					<view v-for="tab in tabList" :key="tab.name"
						:class="['tab-nav-item', { active: activeTab === tab.name }]" @click="activeTab = tab.name">
						<text>{{ tab.title }}</text>
					</view>
				</view>

				<!-- 任务详情扩展板块 -->
				<view class="tab-content" v-if="activeTab === 'base'">
					<view class="base-info-grid">
						<view class="bi-item" v-for="item in baseInfoList" :key="item.label">
							<text class="bi-label">{{ item.label }}</text>
							<text :class="['bi-val', item.highlight ? 'highlight' : '']">{{ item.value }}</text>
						</view>
					</view>

					<!-- 接送任务详情 -->
					<block v-if="order.type === 'transport'">
						<text class="sub-title">接送任务详情</text>
						<view class="task-card transport-card">
							<view class="task-header">
								<text class="type-tag" :class="getTransportClass(order.subOrderType)">
									{{ getTransportLabel(order.subOrderType) }}
								</text>
								<text class="task-time">{{ order.serviceTime }}</text>
							</view>
							<view class="task-body">
								<view class="task-row">
									<text class="task-label">起点</text>
									<text class="task-value">{{ order.fromAddress || '-' }}</text>
								</view>
								<view class="task-row">
									<text class="task-label">终点</text>
									<text class="task-value">{{ order.toAddress || '-' }}</text>
								</view>
								<view class="task-row contact-row">
									<text class="task-value">{{ order.userName }} — {{ order.userPhone }}</text>
								</view>
							</view>
						</view>
					</block>

					<!-- 上门服务执行要求 -->
					<block v-if="['feeding', 'washing'].includes(order.type)">
						<text class="sub-title">服务执行要求</text>
						<view class="task-card req-card">
							<view class="req-item">
								<text class="req-label">服务地址</text>
								<text class="req-value">{{ order.address }}</text>
							</view>
						</view>
					</block>
				</view>

				<!-- 指派履约者 -->
				<view class="tab-content" v-if="activeTab === 'assignee'">
					<view class="empty-state" v-if="order.statusKey === 'wait_dispatch'">
						<uni-icons type="clock" size="40" color="#ccc"></uni-icons>
						<text class="empty-text">等待派单中...</text>
					</view>
					<view class="assignee-card" v-else>
						<view class="assignee-header">
							<view class="assignee-avatar">
								<image v-if="order.assigneeAvatarUrl" :src="order.assigneeAvatarUrl" mode="aspectFill"
									class="avatar-img"></image>
								<uni-icons v-else type="person" size="30" color="#aaa"></uni-icons>
							</view>
							<view class="assignee-info">
								<text class="assignee-name">{{ order.assigneeName }}</text>
								<text class="assignee-phone">联系电话：{{ order.assigneePhone }}</text>
								<text class="assignee-zone">归属区域：{{ order.assigneeZone }}</text>
							</view>
						</view>
					</view>
				</view>

				<!-- 服务进度 -->
				<view class="tab-content" v-if="activeTab === 'progress'">
					<view class="empty-state"
						v-if="['wait_dispatch', 'wait_accept'].includes(order.statusKey) || serviceTimeline.length === 0">
						<uni-icons type="info" size="40" color="#ccc"></uni-icons>
						<text class="empty-text">服务尚未开始或暂无进度</text>
					</view>
					<view class="timeline" v-else>
						<view class="tl-item" v-for="(tl, i) in serviceTimeline" :key="i">
							<view class="tl-dot"></view>
							<view class="tl-body">
								<text class="tl-time">{{ tl.time }}</text>
								<text class="tl-title">{{ tl.title }}</text>
								<text class="tl-desc">{{ tl.desc }}</text>
								<view class="tl-media" v-if="tl.media && tl.media.length">
									<view v-for="(item, idx) in tl.media" :key="idx" class="media-item">
										<image v-if="item.type === 'image'" mode="aspectFill" :src="item.url"
											class="p-img" @click="previewImage(item.url, tl.media)"></image>
										<view v-else-if="item.type === 'video'" class="p-video-box"
											@click="openVideoPreview(item.url)">
											<image src="/static/video-placeholder.png" mode="aspectFill" class="p-img"
												style="background:#000;"></image>
											<view class="play-icon-overlay">
												<uni-icons type="videocam-filled" size="30" color="#fff"></uni-icons>
											</view>
										</view>
									</view>
								</view>
							</view>
						</view>
					</view>
				</view>

				<!-- 订单日志 -->
				<view class="tab-content" v-if="activeTab === 'log'">
					<view class="empty-state" v-if="orderLogs.length === 0">
						<uni-icons type="info" size="40" color="#ccc"></uni-icons>
						<text class="empty-text">暂无订单日志</text>
					</view>
					<view class="timeline" v-else>
						<view class="tl-item" v-for="(log, i) in orderLogs" :key="i">
							<view class="tl-dot log-dot"></view>
							<view class="tl-body">
								<text class="tl-time">{{ log.time }}</text>
								<text class="tl-title">{{ log.title }}</text>
								<text class="tl-desc">{{ log.desc }}</text>
							</view>
						</view>
					</view>
				</view>

				<!-- 投诉记录 -->
				<view class="tab-content" v-if="activeTab === 'complaint'">
					<view class="empty-state" v-if="complaintList.length === 0">
						<uni-icons type="info" size="40" color="#ccc"></uni-icons>
						<text class="empty-text">暂无投诉记录</text>
					</view>
					<view class="timeline" v-else>
						<view class="tl-item" v-for="(complaint, i) in complaintList" :key="i">
							<view class="tl-dot" style="background: #f56c6c;"></view>
							<view class="tl-body">
								<text class="tl-time">{{ complaint.createTime }}</text>
								<text class="tl-title">投诉原因：{{ complaint.reason }}</text>
								<view v-if="complaint.photoUrls" class="tl-media">
									<view v-for="(url, idx) in (complaint.photoUrls || '').split(',')" :key="idx"
										class="media-item">
										<image mode="aspectFill" :src="url" class="p-img"
											@click="previewImage(url, (complaint.photoUrls || '').split(','))"></image>
									</view>
								</view>
							</view>
						</view>
					</view>
				</view>

				<!-- 服务变更记录 -->
				<view class="tab-content" v-if="activeTab === 'serviceChange'">
					<view class="empty-state" v-if="serviceChangeList.length === 0">
						<uni-icons type="info" size="40" color="#ccc"></uni-icons>
						<text class="empty-text">暂无服务变更记录</text>
					</view>
					<view class="timeline" v-else>
						<view class="tl-item" v-for="(change, i) in serviceChangeList" :key="i">
							<view class="tl-dot" style="background: #409eff;"></view>
							<view class="tl-body">
								<text class="tl-time">{{ change.createTime }}</text>
								<text class="tl-title">服务变更 - {{ change.service }}</text>
								<text class="tl-desc">申诉理由：{{ change.reason }}</text>
								<text class="tl-desc" v-if="change.auditStatus === 1"
									style="color:#67c23a;">审核状态：已通过</text>
								<text class="tl-desc" v-else-if="change.auditStatus === 2"
									style="color:#f56c6c;">审核状态：已驳回</text>
								<text class="tl-desc" v-else style="color:#e6a23c;">审核状态：待审核</text>
								<view v-if="change.photoUrls" class="tl-media">
									<view v-for="(url, idx) in (change.photoUrls || '').split(',')" :key="idx"
										class="media-item">
										<image mode="aspectFill" :src="url" class="p-img"
											@click="previewImage(url, (change.photoUrls || '').split(','))"></image>
									</view>
								</view>
							</view>
						</view>
					</view>
				</view>
			</view>

		</view>

		<!-- 视频全屏预览 -->
		<view class="video-preview-mask" v-if="videoPreview.visible" @click.stop="closeVideoPreview">
			<video :src="videoPreview.url" autoplay controls class="preview-video" @click.stop></video>
			<view class="close-video-btn" @click.stop="closeVideoPreview">
				<uni-icons type="closeempty" size="24" color="#fff"></uni-icons>
			</view>
		</view>

		<!-- 底部操作按钮 -->
		<view class="cancel-bar safe-bottom"
			v-if="!loading && (['wait_dispatch', 'wait_accept'].includes(order.statusKey) || ['serving', 'done'].includes(order.statusKey) && order.fulfiller)">
			<button v-if="['wait_dispatch', 'wait_accept'].includes(order.statusKey)" class="cancel-order-btn"
				@click="onCancelOrder">取消订单</button>
			<button v-if="['serving', 'done'].includes(order.statusKey) && order.fulfiller" class="complaint-btn"
				@click="onComplaint">投诉订单</button>
		</view>

		<!-- 自定义取消订单弹窗 -->
		<view class="custom-modal" v-if="showCancelModal">
			<view class="modal-mask" @click="closeCancelModal"></view>
			<view class="modal-content">
				<view class="modal-title">提示</view>
				<view class="modal-body">
					<view style="margin-bottom: 20rpx; font-size: 28rpx; color: #666;">确定要取消订单 [{{ order.id }}] 吗？
					</view>
					<textarea class="cancel-input" v-model="cancelReason" placeholder="必填，请输入取消原因"
						placeholder-class="ph-color" :show-confirm-bar="false"></textarea>
				</view>
				<view class="modal-footer">
					<view class="modal-btn btn-cancel" @click="closeCancelModal">取消</view>
					<view class="modal-btn btn-confirm" @click="confirmCancelOrder">确定</view>
				</view>
			</view>
		</view>

	</view>
</template>

<script setup>
import { ref, reactive, computed, watch } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import navBar from '@/components/nav-bar/index.vue'
import { getSubOrderInfo, cancelSubOrder } from '@/api/order/subOrder'
import { getPet } from '@/api/archieves/pet'
import { getCustomer } from '@/api/archieves/customer'
import { getFulfiller } from '@/api/fulfiller/fulfiller'
import { listSubOrderLog } from '@/api/order/subOrderLog'
import { listComplaintByOrder } from '@/api/fulfiller/complaint'
import { listSubOrderAppealByOrderId } from '@/api/order/subOrderAppeal'

const activeTab = ref('base')
const activeService = ref('transport')
const orderId = ref('')
const loading = ref(true)

const tabList = [
	{ title: '基础信息', name: 'base' },
	{ title: '履约者', name: 'assignee' },
	{ title: '服务进度', name: 'progress' },
	{ title: '订单日志', name: 'log' },
	{ title: '服务变更', name: 'serviceChange' },
	{ title: '投诉记录', name: 'complaint' }
]

const currentServiceName = computed(() => {
	const map = { transport: '宠物接送', feed: '上门喂遛', wash: '上门洗护' }
	return map[activeService.value]
})

const order = reactive({
	id: '',
	code: '',
	statusKey: 'pending_service',
	statusText: '待服务',
	status: 2,
	petName: '',
	petBreed: '',
	petAge: '',
	petWeight: '',
	petGender: '',
	petVaccine: '',
	petCharacter: '',
	petHealth: '',
	userName: '',
	userPhone: '',
	address: '',
	shopName: '',
	createTime: '',
	bookTime: '',
	packageName: '',
	remark: '',
	assigneeName: '',
	cancelTime: '',
	orderCommission: 0,
	pickAddress: '',
	pickTime: '',
	sendAddress: '',
	sendTime: '',
	fromAddress: '',
	toAddress: '',
	type: 'transport', // 对应后端 transport/feeding/washing
	subOrderType: 0,   // 接送子类型
	service: '',
	pet: '',
	customer: '',
	fulfiller: '',
	fulfillerName: '',
	assigneePhone: '-',
	assigneeZone: '-',
	petAvatarUrl: '',
	userAvatarUrl: '',
	assigneeAvatarUrl: ''
})

const orderLogsData = ref([])
const fulfillerLogsData = ref([])
const complaintList = ref([])
const serviceChangeList = ref([])

const loadOrderDetail = async (id) => {
	if (!id) return
	loading.value = true
	try {
		const res = await getSubOrderInfo(id)
		console.log('订单详情返回:', res)
		if (res) {
			// 手动逐个赋值，避免 Object.assign 导致的全量字段触发及潜在的递归更新
			order.id = res.id
			order.code = res.code || res.id
			order.status = res.status
			order.statusKey = getStatusKey(res.status)
			order.statusText = getStatusName(res.status)
			order.bookTime = res.serviceTime || '-'
			order.shopName = res.storeName || '-'
			order.userName = res.customerName || '-'
			order.userPhone = res.contactPhoneNumber || '-'
			order.assigneeName = res.fulfillerName || '-'
			order.remark = res.remark || '-'
			order.fromAddress = res.fromAddress || '-'
			order.toAddress = res.toAddress || '-'
			order.address = res.address || res.toAddress || '-'
			order.type = res.type || 'transport'
			order.subOrderType = res.subOrderType
			order.pet = res.usrPet
			order.customer = res.usrCustomer
			order.fulfiller = res.fulfiller
			order.packageName = res.groupPurchasePackageName || res.packageName || '-'
			order.createTime = res.createTime || '-'
			order.orderCommission = res.orderCommission || 0

			// 并行加载关联信息，提升效率并减少串行触发的重演
			const tasks = []
			if (res.usrPet) tasks.push(loadPetInfo(res.usrPet))
			if (res.usrCustomer) tasks.push(loadCustomerInfo(res.usrCustomer))
			if (res.fulfiller) tasks.push(loadFulfillerInfo(res.fulfiller))

			await Promise.all([
				...tasks,
				loadOrderLogs(id),
				loadComplaints(id),
				loadServiceChanges(id)
			])
		}
	} catch (error) {
		console.error('加载订单详情失败:', error)
		uni.showToast({ title: typeof error === 'string' ? error : '请求失败', icon: 'none' })
	} finally {
		loading.value = false
	}
}

const loadPetInfo = async (petId) => {
	try {
		const res = await getPet(petId)
		if (res) {
			const data = res.data || res
			console.log('宠物详情 res:', data)
			order.petName = data.name || '-'
			order.petBreed = data.breed || '-'
			order.petAge = data.age ? `${data.age}岁` : '-'
			order.petWeight = data.weight ? `${data.weight}kg` : '-'
			order.petGender = Number(data.gender) === 1 ? 'male' : (Number(data.gender) > 0 ? 'female' : '')
			order.petVaccine = data.vaccineStatus || '-'
			order.petCharacter = data.cutePersonality || data.personality || '-'
			order.petHealth = data.healthStatus || '-'
			order.petAvatarUrl = data.avatarUrl || ''
		}
	} catch (error) {
		console.error('加载宠物信息失败:', error)
		uni.showToast({ title: typeof error === 'string' ? error : '加载宠物信息失败', icon: 'none' })
	}
}

const loadCustomerInfo = async (customerId) => {
	try {
		const res = await getCustomer(customerId)
		if (res) {
			const data = res.data || res
			console.log('客户详情 res:', data)
			order.userName = data.name || '-'
			order.userPhone = data.phone || '-'
			order.address = data.address || '-'
			order.userAvatarUrl = data.avatarUrl || ''
		}
	} catch (error) {
		console.error('加载客户信息失败:', error)
		uni.showToast({ title: typeof error === 'string' ? error : '加载客户信息失败', icon: 'none' })
	}
}

const loadFulfillerInfo = async (fulfillerId) => {
	try {
		const res = await getFulfiller(fulfillerId)
		if (res) {
			const data = res.data || res
			console.log('履约者详情 res:', data)
			order.assigneeName = data.name || order.assigneeName
			order.assigneePhone = data.phone || '-'
			order.assigneeZone = data.stationName || '-'
			order.assigneeAvatarUrl = data.avatarUrl || data.avatar || ''
		}
	} catch (error) {
		console.error('加载履约者信息失败:', error)
		uni.showToast({ title: typeof error === 'string' ? error : '加载履约者信息失败', icon: 'none' })
	}
}

const loadOrderLogs = async (id) => {
	try {
		const res = await listSubOrderLog({ orderId: id })
		const list = res || []
		orderLogsData.value = list.filter(i => Number(i?.logType) === 0)
		fulfillerLogsData.value = list.filter(i => Number(i?.logType) === 1)
	} catch (error) {
		console.error('加载订单日志失败:', error)
		uni.showToast({ title: typeof error === 'string' ? error : '加载订单日志失败', icon: 'none' })
		orderLogsData.value = []
		fulfillerLogsData.value = []
	}
}

const loadComplaints = async (id) => {
	try {
		const res = await listComplaintByOrder(id)
		complaintList.value = res || []
	} catch (error) {
		console.error('加载投诉记录失败:', error)
		uni.showToast({ title: typeof error === 'string' ? error : '加载投诉记录失败', icon: 'none' })
		complaintList.value = []
	}
}

const loadServiceChanges = async (id) => {
	try {
		const res = await listSubOrderAppealByOrderId(id)
		serviceChangeList.value = res || []
	} catch (error) {
		console.error('加载服务变更记录失败:', error)
		uni.showToast({ title: typeof error === 'string' ? error : '加载服务变更记录失败', icon: 'none' })
		serviceChangeList.value = []
	}
}

const getStatusKey = (status) => {
	const map = { 0: 'wait_dispatch', 1: 'wait_accept', 2: 'pending_service', 3: 'serving', 4: 'done', 5: 'cancel', 6: 'rejected', 7: 'closed' }
	return map[status] || 'serving'
}

const getStatusName = (status) => {
	const map = { 0: '待派单', 1: '待接单', 2: '待服务', 3: '服务中', 4: '已完成', 5: '已取消', 6: '已拒绝', 7: '已关闭' }
	return map[status] || '-'
}

const getTransportLabel = (t) => {
	if (t === 0 || t === '0') return '接'
	if (t === 1 || t === '1') return '送'
	if (t === 2 || t === '2') return '单程接'
	if (t === 3 || t === '3') return '单程送'
	return '接送'
}

const getTransportClass = (t) => {
	if (t === 0 || t === '0' || t === 2 || t === '2') return 'tag-blue'
	return 'tag-orange'
}

const getTypeName = (type) => {
	const map = { transport: '宠物接送', feeding: '上门喂遛', washing: '上门洗护' }
	return map[type] || '-'
}

onLoad((options) => {
	// 防御性校验：id 必须是有效值（非空、非字符串 "undefined"）
	if (options.id && options.id !== 'undefined') {
		orderId.value = options.id
		console.log('订单详情页：接收到的订单ID =', options.id)
		loadOrderDetail(options.id)
	} else {
		console.error('订单详情页：缺少有效的订单ID，options =', options)
		uni.showToast({ title: '订单ID无效', icon: 'none' })
		loading.value = false
	}
	if (options.service) activeService.value = options.service
})

const progressSteps = computed(() => {
	const status = Number(order.status)
	const getSystemLogTime = (step) => {
		const log = (orderLogsData.value || []).find(l => parseInt(l.step) === step)
		return log ? (log.createTime || log.time) : ''
	}
	const getFulfillerLogTime = (step) => {
		const log = (fulfillerLogsData.value || []).find(l => parseInt(l.step) === step)
		return log ? (log.createTime || log.time) : ''
	}

	// 已取消 — 特殊两步流程
	if (status === 5) {
		const cancelTime = getSystemLogTime(5) || order.cancelTime || ''
		return [
			{ label: '商户下单', time: (getSystemLogTime(0) || order.createTime || '').substring(5, 16), done: true, active: false },
			{ label: '已取消', time: cancelTime.substring(5, 16), done: true, active: true }
		]
	}

	// 已拒绝 — 特殊两步流程
	if (status === 6) {
		return [
			{ label: '商户下单', time: (getSystemLogTime(0) || order.createTime || '').substring(5, 16), done: true, active: false },
			{ label: '已拒绝', time: '', done: true, active: true }
		]
	}

	// 已关闭 — 特殊两步流程
	if (status === 7) {
		return [
			{ label: '商户下单', time: (getSystemLogTime(0) || order.createTime || '').substring(5, 16), done: true, active: false },
			{ label: '已关闭', time: '', done: true, active: true }
		]
	}

	// 六步流程（全四字）：商户下单 → 运营派单 → 履约接单 → 等待服务 → 服务进行 → 订单完成
	const steps = [
		{ label: '商户下单', time: getSystemLogTime(0) || order.createTime || '' },
		{ label: '运营派单', time: getSystemLogTime(1) || '' },
		{ label: '履约接单', time: getSystemLogTime(2) || getFulfillerLogTime(0) || '' },
		{ label: '等待服务', time: getSystemLogTime(3) || '' },
		{ label: '服务进行', time: getFulfillerLogTime(99) || '' },
		{ label: '订单完成', time: getSystemLogTime(4) || '' }
	]

	let active = 1 // 默认停在「运营派单」

	switch (status) {
		case 0: // 待派单
			active = 1
			break
		case 1: // 待接单
			active = 2
			steps[2].label = '等待接单'
			break
		case 2: // 待服务
			active = 3
			steps[2].label = '已确认接'
			steps[3].label = '等待服务'
			break
		case 3: // 服务中（到达打卡）
			active = 4
			steps[2].label = '已确认接'
			steps[3].label = '已到达点'
			steps[4].label = '服务进行'
			break
		case 4: // 已完成
			active = 6
			steps[2].label = '已确认接'
			steps[3].label = '已到达点'
			steps[4].label = '服务进行'
			break
	}

	return steps.map((s, i) => ({
		label: s.label,
		time: s.time ? s.time.substring(5, 16) : '',
		done: i < active,
		active: i === active
	}))
})

const baseInfoList = computed(() => {
	const list = [
		{ label: '系统单号', value: order.code || order.id },
		{ label: '服务类型', value: currentServiceName.value },
		{ label: '订单金额', value: `¥${(order.orderCommission / 100).toFixed(2)}`, highlight: true },
		{ label: '归属门店', value: order.shopName },
		{ label: '宠主信息', value: `${order.userName} / ${order.userPhone}` },
		{ label: '预约时间', value: order.bookTime },
		{ label: '团购套餐', value: order.packageName },
		{ label: '创建时间', value: order.createTime },
		{ label: '订单备注', value: order.remark }
	]
	if (order.statusKey === 'cancel') list.push({ label: '取消时间', value: order.cancelTime || '2024-02-02 11:30', highlight: true })
	return list
})

// 视频判定辅助函数
const isVideo = (url) => {
	if (!url) return false;
	const videoExts = ['.mp4', '.mov', '.avi', '.wmv', '.webm', '.ogg'];
	return videoExts.some(ext => String(url).toLowerCase().endsWith(ext));
}

const videoPreview = reactive({
	visible: false,
	url: ''
})

const openVideoPreview = (url) => {
	videoPreview.url = url;
	videoPreview.visible = true;
}

const closeVideoPreview = () => {
	videoPreview.visible = false;
	videoPreview.url = '';
}

const previewImage = (url, mediaList) => {
	let imgUrls = []
	if (Array.isArray(mediaList)) {
		if (mediaList.length > 0 && typeof mediaList[0] === 'string') {
			// 直接的URL数组（服务变更记录）
			imgUrls = mediaList
		} else {
			// 包含type属性的对象数组
			imgUrls = mediaList.filter(m => m.type === 'image').map(m => m.url)
		}
	} else if (typeof mediaList === 'string') {
		// 单个URL
		imgUrls = [mediaList]
	}
	uni.previewImage({
		current: url,
		urls: imgUrls
	});
}

const serviceTimeline = computed(() => {
	const list = fulfillerLogsData.value || []
	return list.map((i) => {
		const rawUrls = i?.photoUrls || [];
		const urlList = Array.isArray(rawUrls) ? rawUrls : (typeof rawUrls === 'string' ? rawUrls.split(',').filter(Boolean) : []);
		const media = urlList.map(url => {
			const type = isVideo(url) ? 'video' : 'image';
			return { type, url }
		});

		return {
			title: i?.title || '-',
			time: i?.createTime || i?.time || '',
			desc: i?.content || '',
			media: media
		}
	})
})

const orderLogs = computed(() => {
	return (orderLogsData.value || []).map(log => ({
		time: log.createTime || log.time || '',
		title: log.title,
		desc: log.content
	}))
})

const showCancelModal = ref(false)
const cancelReason = ref('')

const onCancelOrder = () => {
	cancelReason.value = ''
	showCancelModal.value = true
}

const closeCancelModal = () => {
	showCancelModal.value = false
}

const confirmCancelOrder = async () => {
	const reason = cancelReason.value.trim()
	if (!reason) {
		uni.showToast({ title: '取消原因不能为空', icon: 'none' })
		return
	}
	try {
		uni.showLoading({ title: '处理中' })
		await cancelSubOrder({ orderId: order.id, reason })
		uni.hideLoading()
		uni.showToast({ title: '订单已取消', icon: 'success' })
		showCancelModal.value = false

		// 重新初始化页面数据
		loadOrderDetail(order.id)
	} catch (error) {
		uni.hideLoading()
		console.error('取消订单失败:', error)
		uni.showToast({ title: typeof error === 'string' ? error : '取消失败', icon: 'none' })
	}
}

const onComplaint = () => {
	uni.navigateTo({
		url: `/pages/my/complaint/submit/index?orderId=${order.id}&fulfillerId=${order.fulfiller}&orderCode=${order.code}`
	})
}
</script>

<style lang="scss" scoped>
.order-detail-page {
	background: #f2f3f7;
	min-height: 100vh;
	padding-bottom: 160rpx;
}

.order-header {
	padding: 24rpx 32rpx 16rpx;
}

.order-id-row {
	display: flex;
	align-items: center;
	gap: 16rpx;
	flex-wrap: wrap;
}

.order-id {
	font-size: 26rpx;
	color: #666;
	font-family: monospace;
}

.status-badge {
	font-size: 22rpx;
	padding: 4rpx 16rpx;
	border-radius: 20rpx;
	font-weight: 600;
}

.badge-wait_dispatch {
	background: #fff0f0;
	color: #f44336;
}

.badge-wait_accept {
	background: #fff8e1;
	color: #ff9800;
}

.badge-pending_service {
	background: #e3f2fd;
	color: #49a3ff;
}

.badge-serving {
	background: #e3f2fd;
	color: #2196f3;
}

.badge-done {
	background: #e8f5e9;
	color: #4caf50;
}

.badge-cancel {
	background: #f5f5f5;
	color: #9e9e9e;
}

.service-badge {
	font-size: 22rpx;
	padding: 4rpx 16rpx;
	border-radius: 20rpx;
	background: #fff3e0;
	color: #ff9500;
}

.progress-card {
	background: #fff;
	margin: 0 24rpx 24rpx;
	border-radius: 28rpx;
	padding: 32rpx 16rpx 24rpx;
}

.progress-steps {
	display: flex;
	align-items: flex-start;
}

.step-item {
	display: flex;
	flex-direction: column;
	align-items: center;
	flex: 1;
	position: relative;
	z-index: 1;
}

.step-circle {
	width: 44rpx;
	height: 44rpx;
	border-radius: 50%;
	background: #e0e0e0;
	display: flex;
	align-items: center;
	justify-content: center;
	margin-bottom: 8rpx;
	position: relative;
	z-index: 2;
}

.step-num {
	font-size: 20rpx;
	color: #fff;
}

.step-item.done .step-circle,
.step-item.active .step-circle {
	background: #ff9500;
}

.step-line {
	position: absolute;
	top: 22rpx;
	left: 50%;
	width: 100%;
	height: 4rpx;
	background: #e0e0e0;
	z-index: 0;
}

.step-line.done {
	background: #ff9500;
}

.step-label {
	font-size: 20rpx;
	color: #999;
	text-align: center;
}

.step-item.done .step-label,
.step-item.active .step-label {
	color: #ff9500;
	font-weight: 600;
}

.step-time {
	font-size: 18rpx;
	color: #bbb;
	margin-top: 4rpx;
}

.info-row-cards {
	display: flex;
	gap: 20rpx;
	margin: 0 24rpx 24rpx;
}

.info-card {
	flex: 1;
	background: #fff;
	border-radius: 28rpx;
	padding: 24rpx;
	min-width: 0;
}

.card-label {
	display: block;
	font-size: 24rpx;
	font-weight: 700;
	color: #333;
	margin-bottom: 20rpx;
	border-left: 6rpx solid #ff9500;
	padding-left: 12rpx;
}

.pet-header {
	display: flex;
	align-items: center;
	gap: 16rpx;
	margin-bottom: 20rpx;
}

.pet-avatar,
.user-avatar,
.assignee-avatar {
	width: 80rpx;
	height: 80rpx;
	border-radius: 50%;
	background: #f0f2f5;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	flex-shrink: 0;

	.avatar-img {
		width: 100%;
		height: 100%;
	}
}

.pet-basic {
	flex: 1;
	min-width: 0;
}

.pet-name {
	display: block;
	font-size: 28rpx;
	font-weight: bold;
	color: #222;
}

.gender-male {
	color: #409eff;
	margin-left: 4rpx;
}

.gender-female {
	color: #f56c6c;
	margin-left: 4rpx;
}

.pet-tags {
	display: flex;
	flex-wrap: wrap;
	gap: 12rpx;
	margin-top: 10rpx;
	align-items: center;
}

.mini-tag {
	font-size: 20rpx;
	background: #f5f5f5;
	border-radius: 8rpx;
	padding: 4rpx 12rpx;
	color: #666;
	white-space: nowrap;
}

.breed-badge {
	font-size: 20rpx;
	background: #ffe0b2;
	color: #e65100;
	border-radius: 8rpx;
	padding: 4rpx 12rpx;
	white-space: nowrap;
}

.pet-attrs {
	display: flex;
	flex-wrap: wrap;
	gap: 12rpx 0;
}

.attr-item {
	width: 50%;
}

.attr-item.full {
	width: 100%;
}

.attr-label {
	display: block;
	font-size: 20rpx;
	color: #aaa;
}

.attr-val {
	display: block;
	font-size: 22rpx;
	color: #333;
}

.attr-val.highlight {
	color: #4caf50;
}

.user-header {
	display: flex;
	align-items: center;
	gap: 16rpx;
	margin-bottom: 20rpx;
}

.user-name-text {
	display: block;
	font-size: 28rpx;
	font-weight: bold;
	color: #222;
}

.user-phone {
	display: block;
	font-size: 24rpx;
	color: #666;
}

.service-address-box {
	background: #fff8f0;
	border-radius: 16rpx;
	padding: 16rpx;
}

.addr-label {
	display: block;
	font-size: 20rpx;
	color: #ff9500;
	margin-bottom: 6rpx;
}

.addr-text {
	display: block;
	font-size: 22rpx;
	color: #333;
	line-height: 1.5;
}

.detail-tabs-wrap {
	margin: 0 24rpx;
	background: #fff;
	border-radius: 28rpx;
	overflow: hidden;
}

.tab-nav {
	display: flex;
	border-bottom: 2rpx solid #EEEEEE;
}

.tab-nav-item {
	flex: 1;
	text-align: center;
	padding: 24rpx 0;
	font-size: 24rpx;
	color: #666;
	position: relative;
}

.tab-nav-item.active {
	color: #ff9500;
	font-weight: bold;
}

.tab-nav-item.active::after {
	content: '';
	position: absolute;
	bottom: 0;
	left: 50%;
	transform: translateX(-50%);
	width: 48rpx;
	height: 6rpx;
	background: #ff9500;
	border-radius: 6rpx;
}

.tab-content {
	padding: 28rpx;
	min-height: 280rpx;
}

.base-info-grid {
	display: flex;
	flex-wrap: wrap;
	gap: 20rpx;
	margin-bottom: 32rpx;
}

.bi-item {
	width: calc(50% - 10rpx);
	background: #f8f8f8;
	border-radius: 16rpx;
	padding: 16rpx 20rpx;
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	justify-content: center;
}

.bi-label {
	display: block;
	font-size: 20rpx;
	color: #aaa;
	margin-bottom: 8rpx;
}

.bi-val {
	display: block;
	font-size: 24rpx;
	color: #333;
	font-weight: 500;
	word-break: break-all;
	line-height: 1.4;
}

.bi-val.highlight {
	color: #f44336;
}

.sub-title {
	display: block;
	font-size: 28rpx;
	font-weight: bold;
	color: #333;
	margin: 12rpx 0 24rpx;
}

/* 任务卡片样式 */
.task-card {
	padding: 24rpx;
	background: #fff;
	border: 2rpx solid #EEEEEE;
	border-radius: 12rpx;
	margin-bottom: 20rpx;
	box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.02);
}

.task-header {
	display: flex;
	align-items: center;
	gap: 16rpx;
	margin-bottom: 20rpx;
}

.type-tag {
	font-size: 22rpx;
	padding: 4rpx 12rpx;
	border-radius: 6rpx;
	border: 1rpx solid;
}

.tag-blue {
	color: #007aff;
	background: #eef6ff;
	border-color: #007aff;
}

.tag-orange {
	color: #ff9500;
	background: #fff8f0;
	border-color: #ff9500;
}

.task-time {
	font-size: 26rpx;
	font-weight: bold;
	color: #f56c6c;
}

.task-body {
	display: flex;
	flex-direction: column;
	gap: 12rpx;
}

.task-row {
	display: flex;
	align-items: flex-start;
	gap: 20rpx;
}

.task-label {
	width: 60rpx;
	font-size: 24rpx;
	color: #999;
	flex-shrink: 0;
}

.task-value {
	font-size: 26rpx;
	color: #333;
	line-height: 1.4;
}

.contact-row {
	margin-top: 8rpx;
	padding-top: 8rpx;
}

.contact-row .task-value {
	color: #999;
}

/* 执行要求卡片 */
.req-card {
	background: #f9f9f9;
	border: none;
}

.req-item {
	display: flex;
	align-items: center;
}

.req-label {
	width: 140rpx;
	font-size: 24rpx;
	color: #333;
}

.req-value {
	flex: 1;
	font-size: 26rpx;
	color: #333;
}

.assignee-card {
	background: #f9f9f9;
	border-radius: 24rpx;
	padding: 28rpx;
}

.assignee-header {
	display: flex;
	gap: 24rpx;
}

.assignee-avatar {
	width: 100rpx;
	height: 100rpx;
	border-radius: 50%;
	background: #e0e0e0;
	display: flex;
	align-items: center;
	justify-content: center;
}

.assignee-name {
	display: block;
	font-size: 30rpx;
	font-weight: bold;
	color: #222;
	margin-bottom: 8rpx;
}

.assignee-phone,
.assignee-zone {
	display: block;
	font-size: 24rpx;
	color: #666;
	margin-bottom: 4rpx;
}

.timeline {
	position: relative;
	padding-left: 40rpx;
}

.tl-item {
	position: relative;
	margin-bottom: 40rpx;
	padding-left: 32rpx;
}

.tl-dot {
	position: absolute;
	left: -12rpx;
	top: 8rpx;
	width: 24rpx;
	height: 24rpx;
	border-radius: 50%;
	background: #ff9500;
	border: 4rpx solid #fff;
	box-shadow: 0 0 0 4rpx #ff9500;
}

.tl-item::before {
	content: '';
	position: absolute;
	left: -2rpx;
	top: 32rpx;
	bottom: -40rpx;
	width: 4rpx;
	background: #f0f0f0;
}

.tl-item:last-child::before {
	display: none;
}

.tl-time {
	display: block;
	font-size: 22rpx;
	color: #aaa;
	margin-bottom: 6rpx;
}

.tl-title {
	display: block;
	font-size: 28rpx;
	font-weight: 600;
	color: #222;
	margin-bottom: 6rpx;
}

.tl-desc {
	display: block;
	font-size: 24rpx;
	color: #666;
}

.log-dot {
	background: #e0e0e0;
	box-shadow: 0 0 0 4rpx #e0e0e0;
}

.empty-state {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 80rpx 0;
	gap: 24rpx;
}

.empty-text {
	font-size: 26rpx;
	color: #bbb;
}

.cancel-bar {
	position: fixed;
	bottom: 0;
	left: 0;
	right: 0;
	padding: 24rpx 32rpx;
	background: rgba(255, 255, 255, 0.95);
	box-shadow: 0 -8rpx 28rpx rgba(0, 0, 0, 0.08);
	z-index: 100;
}

.cancel-order-btn {
	width: 100%;
	height: 96rpx;
	font-size: 32rpx;
	font-weight: 600;
	border: 2rpx solid #f44336;
	color: #f44336;
	background: transparent;
	border-radius: 48rpx;
	line-height: 92rpx;

	&::after {
		border: none;
	}
}

.complaint-btn {
	width: 100%;
	height: 96rpx;
	font-size: 32rpx;
	font-weight: 600;
	border: 2rpx solid #ff9800;
	color: #ff9800;
	background: transparent;
	border-radius: 48rpx;
	line-height: 92rpx;

	&::after {
		border: none;
	}
}

/* 骨架屏动画与样式 */
.skeleton-page {
	padding: 24rpx;
}

.skeleton-box {
	background: #e0e0e0;
	border-radius: 16rpx;
	margin-bottom: 24rpx;
	animation: skeleton-shimmer 1.5s infinite linear;
	background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
	background-size: 400% 100%;
}

@keyframes skeleton-shimmer {
	0% {
		background-position: 100% 0;
	}

	100% {
		background-position: -100% 0;
	}
}

.skeleton-header {
	height: 80rpx;
	border-radius: 20rpx;
}

.skeleton-progress {
	height: 120rpx;
	border-radius: 28rpx;
}

.skeleton-row-cards {
	display: flex;
	gap: 20rpx;
	margin-bottom: 24rpx;
}

.skeleton-card {
	flex: 1;
	height: 280rpx;
	border-radius: 28rpx;
	margin-bottom: 0;
}

.skeleton-content {
	height: 500rpx;
	border-radius: 28rpx;
}

/* 渐显进入动画 */
.fade-in {
	animation: fadeIn 0.4s ease-out forwards;
}

@keyframes fadeIn {
	from {
		opacity: 0;
		transform: translateY(10rpx);
	}

	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* 日志媒体相关样式 */
.tl-media {
	display: flex;
	flex-wrap: wrap;
	gap: 16rpx;
	margin-top: 16rpx;
}

.media-item {
	width: 160rpx;
	height: 160rpx;
	border-radius: 12rpx;
	overflow: hidden;
	background: #f0f0f0;
	position: relative;
}

.p-img,
.p-video-box {
	width: 100%;
	height: 100%;
}

.play-icon-overlay {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 60rpx;
	height: 60rpx;
	background: rgba(0, 0, 0, 0.4);
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	pointer-events: none;
}

/* 视频预览弹窗 */
.video-preview-mask {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: #000;
	z-index: 999;
	display: flex;
	align-items: center;
	justify-content: center;
}

.preview-video {
	width: 100%;
	height: 60vh;
}

.close-video-btn {
	position: absolute;
	top: 100rpx;
	right: 40rpx;
	width: 64rpx;
	height: 64rpx;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.2);
	display: flex;
	justify-content: center;
	z-index: 1000;
}

/* 自定义弹窗样式 */
.custom-modal {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 999;
	display: flex;
	align-items: center;
	justify-content: center;
}

.modal-mask {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background-color: rgba(0, 0, 0, 0.5);
}

.modal-content {
	position: relative;
	width: 80%;
	background-color: #fff;
	border-radius: 16rpx;
	overflow: hidden;
	z-index: 1000;
}

.modal-title {
	padding: 30rpx 0 20rpx;
	text-align: center;
	font-size: 32rpx;
	font-weight: bold;
	color: #333;
}

.modal-body {
	padding: 10rpx 40rpx 30rpx;
}

.cancel-input {
	width: 100%;
	height: 160rpx;
	background-color: #f8f8f8;
	border-radius: 8rpx;
	padding: 20rpx;
	font-size: 28rpx;
	box-sizing: border-box;
	color: #333;
}

.ph-color {
	color: #999;
}

.modal-footer {
	display: flex;
	border-top: 2rpx solid #EEEEEE;
}

.modal-btn {
	flex: 1;
	height: 90rpx;
	line-height: 90rpx;
	text-align: center;
	font-size: 30rpx;
	font-weight: 500;
}

.btn-cancel {
	color: #666;
	border-right: 2rpx solid #EEEEEE;
}

.btn-confirm {
	color: #2196f3;
}
</style>
