<!-- 机构端 - 服务订单详情页面 -->
<template>
	<view class="detail-page">
		<!-- #ifdef MP-WEIXIN -->
		<view class="detail-navbar">
			<view class="detail-navbar-back" @click="uni.navigateBack()">
				<text class="back-arrow">‹</text>
				<text class="back-text">返回</text>
			</view>
			<text class="detail-navbar-title">服务订单详情</text>
			<view style="width: 120rpx;"></view>
		</view>
		<!-- #endif -->

		<scroll-view class="detail-scroll" direction="vertical">

			<!-- ① 状态头部 -->
			<view class="status-header" :class="'sh-' + statusKey">
				<view class="sh-main-row">
					<text class="sh-icon">{{ statusIcon }}</text>
					<view class="sh-titles">
						<text class="sh-main-text">{{ statusMainText }}</text>
						<text class="sh-desc-text">{{ statusDescText }}</text>
					</view>
				</view>
				<view class="sh-tags-row">
					<view class="sh-tag" :class="'sht-pay-' + payTagType">
						<text class="sh-tag-label">支付</text>
						<text class="sh-tag-val">{{ payStatusText }}</text>
					</view>
					<view class="sh-tag sht-fulfill">
						<text class="sh-tag-label">服务</text>
						<text class="sh-tag-val">{{ serviceStatusText }}</text>
					</view>
					<view v-if="isAftersale" class="sh-tag sht-aftersale">
						<text class="sh-tag-label">退款</text>
						<text class="sh-tag-val">{{ aftersaleStatusText }}</text>
					</view>
				</view>
			</view>

			<!-- ② 上门地址 & 服务安排 -->
			<view class="section-card mt16">
				<view class="section-card-title">
					<text class="sct-icon">📍</text>
					<text class="sct-text">上门地址</text>
				</view>
				<view class="addr-block">
					<view class="addr-person-row">
						<text class="addr-name">{{ addressData.recipient_name || '服务对象未知' }}</text>
						<text class="addr-phone">{{ maskPhone(addressData.phone) }}</text>
					</view>
					<text class="addr-detail">
						{{ addressData.province }}{{ addressData.city }}{{ addressData.district }}{{ addressData.detail_address }}
					</text>
					<text v-if="!addressData.recipient_name && !addressData.detail_address" class="addr-empty">暂无上门地址</text>
				</view>
				<!-- 服务安排信息，已接单后显示 -->
				<view v-if="order.order_status === 3 || order.order_status === 4" class="logistics-divider"></view>
				<view v-if="order.order_status === 3 || order.order_status === 4" class="logistics-block">
					<view class="logi-left">
						<text class="logi-icon">👨‍⚕️</text>
						<view class="logi-info">
							<text class="logi-company">{{ order.carrier_name || '服务人员待分配' }}</text>
							<view class="logi-no-row">
								<text class="logi-no">工单号：{{ order.tracking_no || '待生成' }}</text>
								<view v-if="order.tracking_no" class="copy-tag" @click="copyText(order.tracking_no)">复制</view>
							</view>
							<text v-if="order.shipped_at" class="logi-time">出发时间：{{ formatTime(order.shipped_at) }}</text>
						</view>
					</view>
				</view>
			</view>

			<!-- ③ 服务/商品项目 -->
			<view class="section-card mt16">
				<view class="section-card-title">
					<text class="sct-icon">🏥</text>
					<text class="sct-text">服务/商品项目</text>
					<text class="sct-count">共 {{ order.items.length }} 项</text>
				</view>
				<view v-if="order.items.length === 0" class="items-empty">
					<text class="items-empty-text">暂无服务项目信息</text>
				</view>
				<view v-for="item in order.items" :key="item.id" class="product-item">
					<image
						:src="item.image_url || '/static/images/default-product.png'"
						class="product-img"
						mode="aspectFill"
					/>
					<view class="product-main">
						<text class="product-name">{{ item.product_name }}</text>
						<view v-if="item.sku_name" class="product-spec-wrap">
							<text class="product-spec">{{ item.sku_name }}</text>
						</view>
						<view class="product-price-row">
							<text class="product-price">¥{{ formatMoney(item.price) }}</text>
							<text class="product-qty">× {{ item.quantity }}</text>
						</view>
					</view>
					<view class="product-subtotal">
						<text class="product-subtotal-label">小计</text>
						<text class="product-subtotal-val">¥{{ formatMoney(item.price * item.quantity) }}</text>
					</view>
				</view>
			</view>

			<!-- ④ 费用明细 -->
			<view class="section-card mt16">
				<view class="section-card-title">
					<text class="sct-icon">💰</text>
					<text class="sct-text">费用明细</text>
				</view>
				<view class="fee-row">
					<text class="fee-label">服务金额</text>
					<text class="fee-val">¥{{ formatMoney(order.product_amount) }}</text>
				</view>
				<view class="fee-row">
					<text class="fee-label">上门服务费</text>
					<text class="fee-val">¥{{ formatMoney(order.shipping_fee) }}</text>
				</view>
				<view v-if="safeNum(order.discount_amount) > 0" class="fee-row">
					<text class="fee-label">优惠/补贴</text>
					<text class="fee-val fee-red">-¥{{ formatMoney(order.discount_amount) }}</text>
				</view>
				<view class="fee-divider"></view>
				<view class="fee-total-row">
					<text class="fee-total-label">实付金额</text>
					<text class="fee-total-val">¥{{ formatMoney(order.total_amount) }}</text>
				</view>
			</view>

			<!-- ⑤ 订单信息 -->
			<view class="section-card mt16">
				<view class="section-card-title">
					<text class="sct-icon">📋</text>
					<text class="sct-text">订单信息</text>
				</view>
				<view class="info-row">
					<text class="info-label">订单编号</text>
					<view class="info-right">
						<text class="info-val info-code">{{ order.order_no }}</text>
						<view class="copy-tag" @click="copyText(order.order_no)">复制</view>
					</view>
				</view>
				<view v-if="order.payment_method" class="info-row">
					<text class="info-label">支付方式</text>
					<text class="info-val">{{ getPayMethodText(order.payment_method) }}</text>
				</view>
				<view class="info-row">
					<text class="info-label">下单时间</text>
					<text class="info-val">{{ formatTime(order.created_at) }}</text>
				</view>
				<view v-if="order.paid_at" class="info-row">
					<text class="info-label">付款时间</text>
					<text class="info-val">{{ formatTime(order.paid_at) }}</text>
				</view>
				<view v-if="order.shipped_at" class="info-row">
					<text class="info-label">派单时间</text>
					<text class="info-val">{{ formatTime(order.shipped_at) }}</text>
				</view>
				<view v-if="order.completed_at" class="info-row">
					<text class="info-label">完成时间</text>
					<text class="info-val">{{ formatTime(order.completed_at) }}</text>
				</view>
			</view>

			<!-- ⑥ 备注 & 操作日志 -->
			<view class="section-card mt16">
				<view class="section-card-title">
					<text class="sct-icon">🗒</text>
					<text class="sct-text">备注与日志</text>
				</view>
				<view v-if="order.remark" class="remark-block buyer-remark">
					<view class="remark-header-row">
						<text class="remark-tag buyer">家属备注</text>
					</view>
					<text class="remark-content">{{ order.remark }}</text>
				</view>
				<view v-if="!order.remark" class="remark-block remark-empty-row">
					<text class="remark-tag buyer">家属备注</text>
					<text class="remark-none">无</text>
				</view>
				<view class="remark-block merchant-remark">
					<view class="remark-header-row">
						<text class="remark-tag merchant">机构备注</text>
						<text class="remark-edit-btn" @click="editMerchantRemark">编辑</text>
					</view>
					<text v-if="order.merchant_remark" class="remark-content">{{ order.merchant_remark }}</text>
					<text v-else class="remark-none">暂无机构备注（仅自己可见）</text>
				</view>
				<view class="timeline-wrap">
					<view class="timeline-title-row">
						<text class="timeline-title">操作日志</text>
					</view>
					<view v-if="timeline.length === 0" class="timeline-empty">
						<text class="timeline-empty-text">暂无操作记录</text>
					</view>
					<view v-for="(log, idx) in timeline" :key="idx" class="timeline-item">
						<view class="tl-dot-wrap">
							<view class="tl-dot" :class="idx === 0 ? 'tl-dot-active' : ''"></view>
							<view v-if="idx < timeline.length - 1" class="tl-line"></view>
						</view>
						<view class="tl-content">
							<text class="tl-action">{{ log.action }}</text>
							<text class="tl-time">{{ formatTime(log.created_at) }}</text>
							<text v-if="log.remark" class="tl-remark">{{ log.remark }}</text>
						</view>
					</view>
				</view>
			</view>

			<!-- ⑦ 退款信息（有售后时显示） -->
			<view v-if="isAftersale" class="section-card mt16 aftersale-card">
				<view class="section-card-title">
					<text class="sct-icon">🔄</text>
					<text class="sct-text">退款信息</text>
					<view class="sct-status-tag">{{ aftersaleStatusText }}</view>
				</view>
				<view class="info-row">
					<text class="info-label">退款类型</text>
					<text class="info-val">{{ order.refund_type || '退款' }}</text>
				</view>
				<view v-if="safeNum(order.refund_amount) > 0" class="info-row">
					<text class="info-label">退款金额</text>
					<text class="info-val fee-red">¥{{ formatMoney(order.refund_amount) }}</text>
				</view>
				<view v-if="order.refund_reason" class="info-row">
					<text class="info-label">退款原因</text>
					<text class="info-val">{{ order.refund_reason }}</text>
				</view>
				<view class="aftersale-btn-row">
					<view class="aftersale-enter-btn" @click="processAftersale">处理退款 ›</view>
				</view>
			</view>

			<!-- 底部安全区占位 -->
			<view style="height: 180rpx;"></view>
		</scroll-view>

		<!-- 底部固定操作栏 -->
		<view class="action-bar">
			<view class="action-bar-inner">
				<view
					v-for="btn in actionButtons"
					:key="btn.key"
					class="action-btn"
					:class="'ab-' + btn.type"
					@click="handleActionBtn(btn.key)"
				>
					{{ btn.label }}
				</view>
			</view>
		</view>

		<!-- 安排服务上门弹窗 -->
		<view v-if="showShipModal" class="modal-mask" @click="closeShipModal">
			<view class="modal-content" @click.stop>
				<view class="modal-header">
					<text class="modal-title">安排服务上门</text>
					<text class="modal-close" @click="closeShipModal">×</text>
				</view>
				<view class="modal-body">
					<view class="form-item">
						<text class="form-label">服务人员</text>
						<picker
							class="form-picker"
							:range="serviceStaff"
							range-key="name"
							@change="onStaffChange"
						>
							<view class="picker-value">
								{{ selectedStaff.name || '请选择服务人员' }}
							</view>
						</picker>
					</view>
					<view class="form-item">
						<text class="form-label">服务工单号</text>
						<input
							class="form-input"
							v-model="serviceCode"
							placeholder="请输入服务工单号"
						/>
					</view>
				</view>
				<view class="modal-footer">
					<view class="modal-btn cancel" @click="closeShipModal">取消</view>
					<view class="modal-btn confirm" @click="confirmShip">确认派单</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script lang="uts">
	import supa from '@/components/supadb/aksupainstance.uts'
	import { requireMerchantAuth } from '@/utils/merchantAuth.uts'

	type OrderItemType = {
		id: string
		order_id: string
		product_id: string
		sku_id: string
		product_name: string
		sku_name: string
		price: number
		quantity: number
		image_url: string
		sku_snapshot: string
	}

	type AddressType = {
		recipient_name: string
		phone: string
		province: string
		city: string
		district: string
		detail_address: string
	}

	type ServiceStaffType = {
		name: string
		code: string
	}

	type ActionBtnType = {
		key: string
		label: string
		type: string
	}

	type TimelineItemType = {
		action: string
		created_at: string
		remark: string
	}

	// ===== 状态映射常量（医养语义） =====
	const STATUS_KEY_MAP : UTSJSONObject = {
		'1': 'pay', '2': 'pending', '3': 'service', '4': 'done',
		'5': 'cancel', '-1': 'cancel', '0': 'refund', '6': 'refund'
	}
	const STATUS_MAIN_TEXT : UTSJSONObject = {
		'1': '待支付', '2': '待接单', '3': '服务进行中', '4': '服务完成',
		'5': '已取消', '-1': '已取消', '0': '退款处理中', '6': '退款处理中'
	}
	const STATUS_DESC : UTSJSONObject = {
		'1': '家属已下单，等待支付',
		'2': '家属已支付，请尽快安排服务人员上门',
		'3': '服务人员已上门，服务进行中',
		'4': '服务已完成，感谢您的服务',
		'5': '订单已取消',
		'-1': '订单已取消',
		'0': '家属申请退款，请及时处理',
		'6': '家属申请退款，请及时处理'
	}
	const STATUS_ICON : UTSJSONObject = {
		'1': '💳', '2': '📋', '3': '🏥', '4': '✅',
		'5': '❌', '-1': '❌', '0': '🔄', '6': '🔄'
	}
	const PAY_STATUS_TEXT : UTSJSONObject = {
		'1': '待付款', '2': '已付款', '3': '已付款', '4': '已付款',
		'5': '未付款', '-1': '未付款', '0': '退款中', '6': '退款中'
	}
	const SERVICE_STATUS_TEXT : UTSJSONObject = {
		'1': '待支付', '2': '待接单', '3': '服务中', '4': '已完成',
		'5': '已取消', '-1': '已取消', '0': '退款处理', '6': '退款处理'
	}
	const PAY_METHOD_TEXT : UTSJSONObject = {
		'wechat': '微信支付', 'alipay': '支付宝', 'balance': '余额支付',
		'wxpay': '微信支付', 'wx': '微信支付'
	}

	// 按钮矩阵配置（医养对应语义）
	const ACTION_BUTTONS_MAP : UTSJSONObject = {
		'1': [
			{ key: 'contact', label: '联系家属', type: 'default' },
			{ key: 'close_order', label: '取消订单', type: 'danger' }
		],
		'2': [
			{ key: 'contact', label: '联系家属', type: 'default' },
			{ key: 'ship', label: '安排服务上门', type: 'primary' }
		],
		'3': [
			{ key: 'contact', label: '联系家属', type: 'default' },
			{ key: 'view_progress', label: '服务进度', type: 'default' },
			{ key: 'complete_service', label: '完成服务', type: 'primary' }
		],
		'4': [
			{ key: 'contact', label: '联系家属', type: 'default' },
			{ key: 'service_record', label: '服务记录', type: 'default' }
		],
		'5': [
			{ key: 'close_reason', label: '取消原因', type: 'default' },
			{ key: 'delete', label: '删除订单', type: 'danger' }
		],
		'-1': [
			{ key: 'close_reason', label: '取消原因', type: 'default' },
			{ key: 'delete', label: '删除订单', type: 'danger' }
		],
		'0': [
			{ key: 'contact', label: '联系家属', type: 'default' },
			{ key: 'process_refund', label: '处理退款', type: 'primary' }
		],
		'6': [
			{ key: 'contact', label: '联系家属', type: 'default' },
			{ key: 'process_refund', label: '处理退款', type: 'primary' }
		]
	}

	export default {
		data() {
			return {
				orderId: '' as string,
				order: {
					id: '',
					order_no: '',
					user_id: '',
					merchant_id: '',
					order_status: 1,
					total_amount: 0,
					product_amount: 0,
					shipping_fee: 0,
					discount_amount: 0,
					paid_amount: 0,
					refund_amount: 0,
					refund_type: '',
					refund_reason: '',
					shipping_address: '',
					remark: '',
					merchant_remark: '',
					carrier_name: '',
					tracking_no: '',
					payment_method: '',
					paid_at: '',
					shipped_at: '',
					completed_at: '',
					created_at: '',
					updated_at: '',
					items: [] as OrderItemType[]
				},
				addressData: {
					recipient_name: '',
					phone: '',
					province: '',
					city: '',
					district: '',
					detail_address: ''
				} as AddressType,
				timeline: [] as TimelineItemType[],

				// 派单弹窗
				showShipModal: false as boolean,
				serviceStaff: [
					{ name: '张医师', code: 'ZYS001' },
					{ name: '李护士', code: 'LHS002' },
					{ name: '王康复师', code: 'WKF003' },
					{ name: '陈营养师', code: 'CYY004' },
					{ name: '刘家政员', code: 'LJZ005' }
				] as ServiceStaffType[],
				selectedStaff: { name: '', code: '' } as ServiceStaffType,
				serviceCode: '' as string
			}
		},

		computed: {
			statusKey(): string {
				const k = String(this.order.order_status)
				return (STATUS_KEY_MAP[k] as string) || 'pay'
			},
			statusMainText(): string {
				const k = String(this.order.order_status)
				return (STATUS_MAIN_TEXT[k] as string) || '未知'
			},
			statusDescText(): string {
				const k = String(this.order.order_status)
				return (STATUS_DESC[k] as string) || ''
			},
			statusIcon(): string {
				const k = String(this.order.order_status)
				return (STATUS_ICON[k] as string) || '📋'
			},
			payStatusText(): string {
				const k = String(this.order.order_status)
				return (PAY_STATUS_TEXT[k] as string) || '-'
			},
			payTagType(): string {
				const s = this.order.order_status
				if (s === 1) return 'pending'
				if (s === 5 || s === -1) return 'none'
				return 'done'
			},
			serviceStatusText(): string {
				const k = String(this.order.order_status)
				return (SERVICE_STATUS_TEXT[k] as string) || '-'
			},
			isAftersale(): boolean {
				return this.order.order_status === 0 || this.order.order_status === 6
			},
			aftersaleStatusText(): string {
				if (this.order.order_status === 0) return '退款中'
				if (this.order.order_status === 6) return '退款处理中'
				return ''
			},
			actionButtons(): ActionBtnType[] {
				const k = String(this.order.order_status)
				const btns = ACTION_BUTTONS_MAP[k]
				if (btns != null && Array.isArray(btns)) {
					return btns as ActionBtnType[]
				}
				return [{ key: 'contact', label: '联系家属', type: 'default' }] as ActionBtnType[]
			}
		},

		async onLoad(options: any) {
			let id = ''
			if (options['id'] != null) {
				id = options['id'] as string
			} else if (options.id != null) {
				id = options.id as string
			}
			const authResult = await requireMerchantAuth({ redirectOnFail: true, toastOnFail: true })
			if (!authResult.ok) {
				return
			}
			if (id !== '') {
				this.orderId = id
				this.loadOrderDetail()
			}
		},

		methods: {

			// ===== 工具方法 =====

			copyText(text: string) {
				if (!text) return
				uni.setClipboardData({
					data: text,
					success: () => { uni.showToast({ title: '复制成功', icon: 'success' }) }
				})
			},

			formatMoney(amount: any): string {
				const num = Number(amount)
				if (isNaN(num)) return '0.00'
				return num.toFixed(2)
			},

			safeNum(val: any): number {
				const n = Number(val)
				return isNaN(n) ? 0 : n
			},

			formatTime(timeStr: string): string {
				if (!timeStr) return '-'
				try {
					const date = new Date(timeStr)
					const year = date.getFullYear()
					const month = (date.getMonth() + 1).toString().padStart(2, '0')
					const day = date.getDate().toString().padStart(2, '0')
					const hour = date.getHours().toString().padStart(2, '0')
					const minute = date.getMinutes().toString().padStart(2, '0')
					return `${year}-${month}-${day} ${hour}:${minute}`
				} catch (_e) { return timeStr }
			},

			maskPhone(phone: string): string {
				if (!phone || phone.length < 7) return phone || ''
				return phone.substring(0, 3) + '****' + phone.substring(phone.length - 4)
			},

			getPayMethodText(method: string): string {
				if (!method) return '-'
				const t = PAY_METHOD_TEXT[method] as string
				return t || method
			},

			// ===== 数据加载 =====

			async loadOrderDetail() {
				try {
					const response = await supa
						.from('ml_orders')
						.select(`*,items:ml_order_items(id,order_id,product_id,sku_id,product_name,sku_name,price,quantity,image_url,specifications)`)
						.eq('id', this.orderId)
						.single()
						.execute()

					if (response.error != null || (response.status ?? 200) >= 400) {
						console.error('获取订单详情失败:', response.error)
						uni.showToast({ title: '加载失败', icon: 'none' })
						return
					}

					let realData = response.data
					if (response.data != null && (response.data as any)['0'] != null) {
						realData = (response.data as any)['0']
					}
					const rawData = realData as UTSJSONObject
					if (rawData == null) return

					this.order = {
						id: String(rawData['id'] ?? '') || '',
						order_no: String(rawData['order_no'] ?? '') || '',
						user_id: String(rawData['user_id'] ?? '') || '',
						merchant_id: String(rawData['merchant_id'] ?? '') || '',
						order_status: Number(rawData['order_status'] ?? 0) || 1,
						total_amount: Number(rawData['total_amount'] ?? 0) || 0,
						product_amount: Number(rawData['product_amount'] ?? 0) || 0,
						shipping_fee: Number(rawData['shipping_fee'] ?? 0) || 0,
						discount_amount: Number(rawData['discount_amount'] ?? 0) || 0,
						paid_amount: Number(rawData['paid_amount'] ?? 0) || 0,
						refund_amount: Number(rawData['refund_amount'] ?? 0) || 0,
						refund_type: String(rawData['refund_type'] ?? '') || '',
						refund_reason: String(rawData['refund_reason'] ?? '') || '',
						shipping_address: String(rawData['shipping_address'] ?? '') || '{}',
						remark: String(rawData['remark'] ?? '') || '',
						merchant_remark: String(rawData['merchant_remark'] ?? '') || '',
						carrier_name: String(rawData['carrier_name'] ?? '') || '',
						tracking_no: String(rawData['tracking_no'] ?? '') || '',
						payment_method: String(rawData['payment_method'] ?? '') || '',
						paid_at: String(rawData['paid_at'] ?? '') || '',
						shipped_at: String(rawData['shipped_at'] ?? '') || '',
						completed_at: String(rawData['completed_at'] ?? '') || '',
						created_at: String(rawData['created_at'] ?? '') || '',
						updated_at: String(rawData['updated_at'] ?? '') || '',
						items: []
					}

					// 多策略解析服务项目数组
					let itemsArr : Array<any> | null = rawData.getArray('items')
					if (itemsArr == null || itemsArr.length === 0) {
						itemsArr = rawData.getArray('ml_order_items')
					}
					if (itemsArr == null || itemsArr.length === 0) {
						try {
							const rawStr = JSON.stringify(rawData)
							const parsedObj = JSON.parse(rawStr) as UTSJSONObject
							const fromParsed = parsedObj.getArray('items') ?? parsedObj.getArray('ml_order_items')
							if (fromParsed != null && fromParsed.length > 0) {
								itemsArr = fromParsed
							}
						} catch (_e) { console.warn('[OD] fallback JSON parse 失败', _e) }
					}
					const tempItems : OrderItemType[] = []
					if (itemsArr != null && itemsArr.length > 0) {
						for (let i = 0; i < itemsArr.length; i++) {
							const _rawItem = itemsArr[i]
							const orderItem = (_rawItem instanceof UTSJSONObject ? _rawItem : new UTSJSONObject(_rawItem)) as UTSJSONObject
							tempItems.push({
								id: String(orderItem['id'] ?? '') || '',
								order_id: String(orderItem['order_id'] ?? '') || '',
								product_id: String(orderItem['product_id'] ?? '') || '',
								sku_id: String(orderItem['sku_id'] ?? '') || '',
								product_name: String(orderItem['product_name'] ?? '') || '',
								sku_name: String(orderItem['sku_name'] ?? '') || '',
								price: Number(orderItem['price'] ?? 0) || 0,
								quantity: Number(orderItem['quantity'] ?? 0) || 0,
								image_url: String(orderItem['image_url'] ?? '') || '',
								sku_snapshot: String(orderItem['specifications'] ?? orderItem['sku_name'] ?? '') || ''
							} as OrderItemType)
						}
					}
					this.order.items = tempItems

					this.parseAddress()
					this.buildTimeline()
				} catch (e) {
					console.error('获取订单详情异常:', e)
				}
			},

			parseAddress() {
				try {
					const addrStr = this.order.shipping_address
					if (!addrStr || addrStr === '{}') return
					const raw = JSON.parse(addrStr) as UTSJSONObject
					this.addressData = {
						recipient_name: String(raw['recipient_name'] ?? raw['name'] ?? '') || '',
						phone: String(raw['phone'] ?? raw['mobile'] ?? '') || '',
						province: String(raw['province'] ?? '') || '',
						city: String(raw['city'] ?? '') || '',
						district: String(raw['district'] ?? '') || '',
						detail_address: String(raw['detail_address'] ?? raw['address'] ?? raw['detail'] ?? '') || ''
					}
				} catch (e) {
					console.error('解析地址失败:', e)
				}
			},

			buildTimeline() {
				const tl : TimelineItemType[] = []
				if (this.order.completed_at) {
					tl.push({ action: '服务完成', created_at: this.order.completed_at, remark: '' })
				}
				if (this.order.shipped_at) {
					const rm = this.order.carrier_name ? `服务人员：${this.order.carrier_name}` : ''
					tl.push({ action: '服务人员已出发', created_at: this.order.shipped_at, remark: rm })
				}
				if (this.order.paid_at) {
					tl.push({ action: '家属完成付款', created_at: this.order.paid_at, remark: '' })
				}
				if (this.order.created_at) {
					tl.push({ action: '订单创建', created_at: this.order.created_at, remark: '' })
				}
				this.timeline = tl
			},

			// ===== 按钮统一分发 =====

			handleActionBtn(key: string) {
				if (key === 'contact') { this.contactBuyer(); return }
				if (key === 'ship') { this.openShipModal(); return }
				if (key === 'view_progress') { this.viewProgress(); return }
				if (key === 'complete_service') { this.completeService(); return }
				if (key === 'service_record') { uni.showToast({ title: '服务记录开发中', icon: 'none' }); return }
				if (key === 'close_order') { this.cancelOrder(); return }
				if (key === 'delete') { this.deleteOrder(); return }
				if (key === 'process_refund') { this.processAftersale(); return }
				if (key === 'close_reason') {
					uni.showModal({
						title: '取消原因',
						content: this.order.remark || '暂无取消原因记录',
						showCancel: false
					})
					return
				}
			},

			// ===== 具体操作方法 =====

			contactBuyer() {
				uni.navigateTo({ url: `/pages/mall/merchant/chat?userId=${this.order.user_id}` })
			},

			openShipModal() {
				this.showShipModal = true
			},

			closeShipModal() {
				this.showShipModal = false
				this.selectedStaff = { name: '', code: '' }
				this.serviceCode = ''
			},

			onStaffChange(e: any) {
				const index = e.detail.value as number
				this.selectedStaff = this.serviceStaff[index]
			},

			async confirmShip() {
				if (!this.selectedStaff.name) {
					uni.showToast({ title: '请选择服务人员', icon: 'none' }); return
				}
				if (!this.serviceCode) {
					uni.showToast({ title: '请输入服务工单号', icon: 'none' }); return
				}
				try {
					const response = await supa
						.from('ml_orders')
						.update({
							order_status: 3,
							shipping_status: 2,
							carrier_name: this.selectedStaff.name,
							tracking_no: this.serviceCode,
							shipped_at: new Date().toISOString(),
							updated_at: new Date().toISOString()
						})
						.eq('id', this.order.id)
						.execute()

					if (response.error != null || (response.status ?? 200) >= 400) {
						const msg = response.error?.message ?? '请检查网络或登录状态'
						uni.showToast({ title: '派单失败：' + msg, icon: 'none', duration: 4000 })
						return
					}
					uni.showToast({ title: '派单成功', icon: 'success' })
					this.closeShipModal()
					this.loadOrderDetail()
				} catch (e) {
					uni.showToast({ title: '派单发生异常', icon: 'none' })
				}
			},

			viewProgress() {
				uni.navigateTo({ url: `/pages/mall/merchant/logistics?orderId=${this.order.id}` })
			},

			async completeService() {
				uni.showModal({
					title: '确认完成服务',
					content: '确认服务已完成？完成后将通知家属确认。',
					success: async (res) => {
						if (res.confirm) {
							try {
								const response = await supa
									.from('ml_orders')
									.update({
										order_status: 4,
										completed_at: new Date().toISOString(),
										updated_at: new Date().toISOString()
									})
									.eq('id', this.order.id)
									.execute()
								if (response.error != null || (response.status ?? 200) >= 400) {
									uni.showToast({ title: '操作失败', icon: 'none' }); return
								}
								uni.showToast({ title: '服务完成', icon: 'success' })
								this.loadOrderDetail()
							} catch (e) {
								uni.showToast({ title: '操作失败', icon: 'none' })
							}
						}
					}
				})
			},

			cancelOrder() {
				uni.showModal({
					title: '取消订单',
					content: '确认取消此服务订单吗？',
					success: async (res) => {
						if (res.confirm) {
							try {
								const response = await supa
									.from('ml_orders')
									.update({
										order_status: 5,
										updated_at: new Date().toISOString()
									})
									.eq('id', this.order.id)
									.execute()
								if (response.error != null || (response.status ?? 200) >= 400) {
									uni.showToast({ title: '操作失败', icon: 'none' }); return
								}
								uni.showToast({ title: '订单已取消', icon: 'success' })
								this.loadOrderDetail()
							} catch (e) {
								uni.showToast({ title: '操作失败', icon: 'none' })
							}
						}
					}
				})
			},

			processAftersale() {
				uni.showToast({ title: '退款处理开发中', icon: 'none' })
			},

			editMerchantRemark() {
				uni.showModal({
					title: '机构备注',
					content: '该功能需要后端接口支持，待接入',
					showCancel: false
				})
			},

			async deleteOrder() {
				uni.showModal({
					title: '确认删除',
					content: '删除后不可恢复，确定要删除吗？',
					success: async (res) => {
						if (res.confirm) {
							try {
								const response = await supa
									.from('ml_orders')
									.delete()
									.eq('id', this.order.id)
									.execute()
								if (response.error != null || (response.status ?? 200) >= 400) {
									uni.showToast({ title: '删除失败', icon: 'none' }); return
								}
								uni.showToast({ title: '删除成功', icon: 'success' })
								setTimeout(() => { uni.navigateBack() }, 1500)
							} catch (e) {
								uni.showToast({ title: '删除失败', icon: 'none' })
							}
						}
					}
				})
			}
		}
	}
</script>

<style>
	/* ===== 页面基础 ===== */
	.detail-page {
		background-color: #f0f0f0;
		min-height: 100vh;
	}

	.detail-scroll {
		flex: 1;
	}

	.mt16 { margin-top: 16rpx; }

	/* ===== 导航栏 ===== */
	.detail-navbar {
		display: flex;
		flex-direction: row;
		align-items: flex-end;
		background-color: #ffffff;
		border-bottom-width: 1rpx;
		border-bottom-style: solid;
		border-bottom-color: #eeeeee;
		box-sizing: border-box;
		padding-top: var(--status-bar-height);
		height: calc(88rpx + var(--status-bar-height));
	}

	.detail-navbar-back {
		display: flex;
		flex-direction: row;
		align-items: center;
		padding: 0 30rpx;
		height: 88rpx;
		width: 120rpx;
	}

	.back-arrow {
		font-size: 44rpx;
		color: #333333;
		line-height: 1;
		margin-right: 4rpx;
	}

	.back-text {
		font-size: 28rpx;
		color: #333333;
	}

	.detail-navbar-title {
		flex: 1;
		text-align: center;
		font-size: 32rpx;
		font-weight: 600;
		color: #1a1a1a;
		height: 88rpx;
		line-height: 88rpx;
	}

	/* ===== 状态头部 ===== */
	.status-header {
		padding: 32rpx 30rpx 24rpx 30rpx;
	}

	/* 医养状态色系 */
	.sh-pay       { background: linear-gradient(135deg, #FF7800 0%, #ff9500 100%); }
	.sh-pending   { background: linear-gradient(135deg, #A6F1E4 0%, #69DFC2 100%); }
	.sh-service   { background: linear-gradient(135deg, #4CAF50 0%, #2E7D32 100%); }
	.sh-done      { background: linear-gradient(135deg, #26A69A 0%, #00796B 100%); }
	.sh-cancel    { background: linear-gradient(135deg, #90A4AE 0%, #607D8B 100%); }
	.sh-refund    { background: linear-gradient(135deg, #FF7043 0%, #E64A19 100%); }

	.sh-main-row {
		display: flex;
		flex-direction: row;
		align-items: center;
		margin-bottom: 20rpx;
	}

	.sh-icon {
		font-size: 56rpx;
		margin-right: 20rpx;
	}

	.sh-titles {
		flex: 1;
		display: flex;
		flex-direction: column;
	}

	.sh-main-text {
		font-size: 38rpx;
		font-weight: 700;
		color: #ffffff;
		margin-bottom: 6rpx;
	}

	.sh-desc-text {
		font-size: 24rpx;
		color: rgba(255,255,255,0.85);
	}

	.sh-tags-row {
		display: flex;
		flex-direction: row;
		align-items: center;
	}

	.sh-tag {
		display: flex;
		flex-direction: row;
		align-items: center;
		background-color: rgba(255,255,255,0.18);
		border-radius: 6rpx;
		padding: 6rpx 14rpx;
		margin-right: 12rpx;
	}

	.sh-tag-label {
		font-size: 20rpx;
		color: rgba(255,255,255,0.75);
		margin-right: 6rpx;
	}

	.sh-tag-val {
		font-size: 22rpx;
		color: #ffffff;
		font-weight: 500;
	}

	.sht-pay-pending .sh-tag-val { color: #ffe082; }
	.sht-pay-done .sh-tag-val   { color: #b9fbc0; }
	.sht-pay-none .sh-tag-val   { color: rgba(255,255,255,0.5); }
	.sht-aftersale { background-color: rgba(255,255,255,0.25); }

	/* ===== 通用卡片 ===== */
	.section-card {
		background-color: #ffffff;
		border-radius: 0;
	}

	.section-card-title {
		display: flex;
		flex-direction: row;
		align-items: center;
		padding: 22rpx 30rpx 18rpx 30rpx;
		border-bottom-width: 1rpx;
		border-bottom-style: solid;
		border-bottom-color: #f0f0f0;
	}

	.sct-icon {
		font-size: 30rpx;
		margin-right: 10rpx;
	}

	.sct-text {
		font-size: 28rpx;
		font-weight: 600;
		color: #1a1a1a;
		flex: 1;
	}

	.sct-count {
		font-size: 24rpx;
		color: #999;
	}

	.sct-status-tag {
		font-size: 22rpx;
		color: #E64A19;
		background-color: #fff3e0;
		padding: 4rpx 14rpx;
		border-radius: 20rpx;
	}

	/* ===== 上门地址块 ===== */
	.addr-block {
		padding: 20rpx 30rpx;
	}

	.addr-person-row {
		display: flex;
		flex-direction: row;
		align-items: center;
		margin-bottom: 10rpx;
	}

	.addr-name {
		font-size: 30rpx;
		font-weight: 600;
		color: #1a1a1a;
		margin-right: 20rpx;
	}

	.addr-phone {
		font-size: 28rpx;
		color: #555;
	}

	.addr-detail {
		font-size: 26rpx;
		color: #666;
		line-height: 1.6;
	}

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

	/* ===== 服务安排块 ===== */
	.logistics-divider {
		height: 1rpx;
		background-color: #f0f0f0;
		margin: 0 30rpx;
	}

	.logistics-block {
		display: flex;
		flex-direction: row;
		align-items: center;
		padding: 20rpx 30rpx;
	}

	.logi-left {
		flex: 1;
		display: flex;
		flex-direction: row;
		align-items: flex-start;
	}

	.logi-icon {
		font-size: 36rpx;
		margin-right: 16rpx;
		padding-top: 4rpx;
	}

	.logi-info {
		flex: 1;
		display: flex;
		flex-direction: column;
	}

	.logi-company {
		font-size: 28rpx;
		font-weight: 600;
		color: #1a1a1a;
		margin-bottom: 6rpx;
	}

	.logi-no-row {
		display: flex;
		flex-direction: row;
		align-items: center;
		margin-bottom: 4rpx;
	}

	.logi-no {
		font-size: 24rpx;
		color: #555;
		margin-right: 12rpx;
	}

	.logi-time {
		font-size: 22rpx;
		color: #999;
	}

	/* ===== 商品/服务列表 ===== */
	.product-item {
		display: flex;
		flex-direction: row;
		align-items: flex-start;
		padding: 20rpx 30rpx;
		border-bottom-width: 1rpx;
		border-bottom-style: solid;
		border-bottom-color: #f5f5f5;
	}

	.product-img {
		width: 160rpx;
		height: 160rpx;
		border-radius: 8rpx;
		margin-right: 20rpx;
		background-color: #f5f5f5;
		flex-shrink: 0;
	}

	.product-main {
		flex: 1;
		display: flex;
		flex-direction: column;
		min-width: 0;
	}

	.product-name {
		font-size: 28rpx;
		color: #1a1a1a;
		line-height: 1.5;
	}

	.product-spec-wrap {
		display: inline-flex;
		margin-top: 8rpx;
		margin-bottom: 8rpx;
	}

	.product-spec {
		font-size: 22rpx;
		color: #888;
		background-color: #f7f7f7;
		padding: 4rpx 12rpx;
		border-radius: 4rpx;
	}

	.product-price-row {
		display: flex;
		flex-direction: row;
		align-items: center;
		margin-top: 8rpx;
	}

	.product-price {
		font-size: 26rpx;
		color: #1a1a1a;
		font-weight: 500;
		margin-right: 16rpx;
	}

	.product-qty {
		font-size: 24rpx;
		color: #999;
	}

	.product-subtotal {
		display: flex;
		flex-direction: column;
		align-items: flex-end;
		margin-left: 16rpx;
		flex-shrink: 0;
	}

	.product-subtotal-label {
		font-size: 20rpx;
		color: #bbb;
		margin-bottom: 4rpx;
	}

	.product-subtotal-val {
		font-size: 28rpx;
		color: #1a1a1a;
		font-weight: 600;
	}

	.items-empty {
		padding: 40rpx 30rpx;
		display: flex;
		flex-direction: row;
		justify-content: center;
	}

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

	/* ===== 金额明细 ===== */
	.fee-row {
		display: flex;
		flex-direction: row;
		justify-content: space-between;
		align-items: center;
		padding: 14rpx 30rpx;
	}

	.fee-label {
		font-size: 26rpx;
		color: #666;
	}

	.fee-val {
		font-size: 26rpx;
		color: #333;
	}

	.fee-red { color: #e64a19; }

	.fee-divider {
		height: 1rpx;
		background-color: #f0f0f0;
		margin: 6rpx 30rpx;
	}

	.fee-total-row {
		display: flex;
		flex-direction: row;
		justify-content: space-between;
		align-items: center;
		padding: 18rpx 30rpx 22rpx 30rpx;
	}

	.fee-total-label {
		font-size: 28rpx;
		font-weight: 600;
		color: #1a1a1a;
	}

	.fee-total-val {
		font-size: 36rpx;
		font-weight: 700;
		color: #e64a19;
	}

	/* ===== 订单信息行 ===== */
	.info-row {
		display: flex;
		flex-direction: row;
		align-items: center;
		padding: 16rpx 30rpx;
		border-bottom-width: 1rpx;
		border-bottom-style: solid;
		border-bottom-color: #f5f5f5;
	}

	.info-label {
		font-size: 26rpx;
		color: #999;
		min-width: 150rpx;
		flex-shrink: 0;
	}

	.info-right {
		flex: 1;
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: flex-end;
	}

	.info-val {
		font-size: 26rpx;
		color: #333;
		flex: 1;
		text-align: right;
	}

	.info-code {
		font-size: 22rpx;
		color: #555;
	}

	.copy-tag {
		font-size: 20rpx;
		color: #09C39D;
		border-width: 1rpx;
		border-style: solid;
		border-color: #09C39D;
		border-radius: 4rpx;
		padding: 2rpx 10rpx;
		margin-left: 12rpx;
		flex-shrink: 0;
	}

	/* ===== 备注区 ===== */
	.remark-block {
		padding: 16rpx 30rpx;
		border-bottom-width: 1rpx;
		border-bottom-style: solid;
		border-bottom-color: #f5f5f5;
	}

	.remark-empty-row {
		display: flex;
		flex-direction: row;
		align-items: center;
	}

	.remark-header-row {
		display: flex;
		flex-direction: row;
		align-items: center;
		margin-bottom: 10rpx;
	}

	.remark-tag {
		font-size: 20rpx;
		border-radius: 4rpx;
		padding: 2rpx 10rpx;
		margin-right: 12rpx;
	}

	.remark-tag.buyer {
		background-color: #E3F7ED;
		color: #09C39D;
	}

	.remark-tag.merchant {
		background-color: #fff3e0;
		color: #e64a19;
	}

	.remark-content {
		font-size: 26rpx;
		color: #333;
		line-height: 1.6;
	}

	.remark-none {
		font-size: 24rpx;
		color: #bbb;
	}

	.remark-edit-btn {
		font-size: 22rpx;
		color: #09C39D;
		margin-left: auto;
	}

	/* ===== 时间线 ===== */
	.timeline-wrap {
		padding: 16rpx 30rpx 20rpx 30rpx;
	}

	.timeline-title-row {
		margin-bottom: 16rpx;
	}

	.timeline-title {
		font-size: 24rpx;
		color: #999;
	}

	.timeline-empty {
		padding: 10rpx 0;
	}

	.timeline-empty-text {
		font-size: 24rpx;
		color: #ccc;
	}

	.timeline-item {
		display: flex;
		flex-direction: row;
		align-items: flex-start;
		margin-bottom: 4rpx;
	}

	.tl-dot-wrap {
		display: flex;
		flex-direction: column;
		align-items: center;
		width: 32rpx;
		margin-right: 16rpx;
		flex-shrink: 0;
	}

	.tl-dot {
		width: 16rpx;
		height: 16rpx;
		border-radius: 8rpx;
		background-color: #d0d0d0;
		margin-top: 6rpx;
	}

	.tl-dot-active {
		background-color: #09C39D;
	}

	.tl-line {
		width: 2rpx;
		flex: 1;
		min-height: 32rpx;
		background-color: #e8e8e8;
		margin-top: 4rpx;
		margin-bottom: 4rpx;
	}

	.tl-content {
		flex: 1;
		display: flex;
		flex-direction: column;
		padding-bottom: 24rpx;
	}

	.tl-action {
		font-size: 26rpx;
		color: #333;
		font-weight: 500;
	}

	.tl-time {
		font-size: 22rpx;
		color: #999;
		margin-top: 4rpx;
	}

	.tl-remark {
		font-size: 22rpx;
		color: #aaa;
		margin-top: 4rpx;
	}

	/* ===== 退款卡片 ===== */
	.aftersale-card {
		border-top-width: 4rpx;
		border-top-style: solid;
		border-top-color: #E64A19;
	}

	.aftersale-btn-row {
		padding: 16rpx 30rpx 20rpx 30rpx;
		display: flex;
		flex-direction: row;
		justify-content: flex-end;
	}

	.aftersale-enter-btn {
		font-size: 26rpx;
		color: #E64A19;
		border-width: 1rpx;
		border-style: solid;
		border-color: #E64A19;
		border-radius: 30rpx;
		padding: 10rpx 30rpx;
	}

	/* ===== 底部固定操作栏 ===== */
	.action-bar {
		position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
		background-color: #ffffff;
		box-shadow: 0 -2rpx 16rpx rgba(0,0,0,0.10);
		padding-bottom: env(safe-area-inset-bottom);
		z-index: 100;
	}

	.action-bar-inner {
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: flex-end;
		padding: 16rpx 24rpx;
		min-height: 104rpx;
		box-sizing: border-box;
	}

	.action-btn {
		height: 72rpx;
		line-height: 72rpx;
		padding: 0 32rpx;
		font-size: 28rpx;
		border-radius: 36rpx;
		margin-left: 16rpx;
		text-align: center;
		flex-shrink: 0;
	}

	.ab-default {
		color: #555;
		border-width: 1rpx;
		border-style: solid;
		border-color: #d0d0d0;
		background-color: #ffffff;
	}

	.ab-primary {
		background-color: #09C39D;
		color: #ffffff;
	}

	.ab-danger {
		background-color: #ffffff;
		color: #e64a19;
		border-width: 1rpx;
		border-style: solid;
		border-color: #e64a19;
	}

	/* ===== 弹窗 ===== */
	.modal-mask {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		background-color: rgba(0,0,0,0.5);
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: flex-end;
		z-index: 200;
	}

	.modal-content {
		width: 100%;
		background-color: #fff;
		border-radius: 24rpx 24rpx 0 0;
		padding-bottom: env(safe-area-inset-bottom);
	}

	.modal-header {
		display: flex;
		flex-direction: row;
		justify-content: space-between;
		align-items: center;
		padding: 30rpx;
		border-bottom-width: 1rpx;
		border-bottom-style: solid;
		border-bottom-color: #f5f5f5;
	}

	.modal-title {
		font-size: 32rpx;
		font-weight: 700;
		color: #1a1a1a;
	}

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

	.modal-body {
		padding: 30rpx;
	}

	.form-item {
		margin-bottom: 24rpx;
	}

	.form-label {
		font-size: 26rpx;
		color: #333;
		display: block;
		margin-bottom: 14rpx;
	}

	.form-picker {
		height: 72rpx;
		border-width: 1rpx;
		border-style: solid;
		border-color: #e5e5e5;
		border-radius: 8rpx;
		padding: 0 20rpx;
		background-color: #fafafa;
	}

	.form-input {
		height: 72rpx;
		border-width: 1rpx;
		border-style: solid;
		border-color: #e5e5e5;
		border-radius: 8rpx;
		padding: 0 20rpx;
		font-size: 28rpx;
		background-color: #fafafa;
	}

	.picker-value {
		height: 72rpx;
		line-height: 72rpx;
		color: #333;
		font-size: 28rpx;
	}

	.modal-footer {
		display: flex;
		flex-direction: row;
		border-top-width: 1rpx;
		border-top-style: solid;
		border-top-color: #f5f5f5;
	}

	.modal-btn {
		flex: 1;
		height: 88rpx;
		line-height: 88rpx;
		text-align: center;
		font-size: 28rpx;
	}

	.modal-btn.cancel {
		color: #666;
		border-right-width: 1rpx;
		border-right-style: solid;
		border-right-color: #f5f5f5;
	}

	.modal-btn.confirm {
		color: #09C39D;
		font-weight: bold;
	}
</style>