import type {
	DeliveryCertificateType,
	DeliveryCheckinPayloadType,
	DeliveryDashboardType,
	DeliveryTimelineItemType,
	DeliveryExceptionPayloadType,
	DeliveryFinishPayloadType,
	DeliveryInfoType,
	DeliveryLocationType,
	DeliveryLoginPayloadType,
	DeliveryLoginResultType,
	DeliveryMessageType,
	DeliveryOrderQueryType,
	DeliveryOrderType,
	DeliveryProgressPayloadType,
	DeliveryRecordType,
	DeliveryEvidenceRecordType,
	DeliveryServiceItemType
} from '@/types/delivery.uts'
import supa, { ensureSupabaseReady } from '@/components/supadb/aksupainstance.uts'
import { getCurrentUser } from '@/utils/store.uts'
import type { UserProfile } from '@/types/mall-types.uts'
import { IS_TEST_MODE } from '@/ak/config.uts'

const DELIVERY_RPC_DASHBOARD = 'rpc_delivery_dashboard'
const DELIVERY_RPC_ORDER_LIST = 'rpc_delivery_order_list'
const DELIVERY_RPC_ORDER_DETAIL = 'rpc_delivery_order_detail'
const DELIVERY_RPC_ACCEPT_ORDER = 'rpc_delivery_accept_order'
const DELIVERY_RPC_REJECT_ORDER = 'rpc_delivery_reject_order'
const DELIVERY_RPC_START_DEPART = 'rpc_delivery_start_depart'
const DELIVERY_RPC_ARRIVE_ORDER = 'rpc_delivery_arrive_order'
const DELIVERY_RPC_CHECKIN_ORDER = 'rpc_delivery_checkin_order'
const DELIVERY_RPC_START_SERVICE = 'rpc_delivery_start_service'
const DELIVERY_RPC_SAVE_PROGRESS = 'rpc_delivery_save_progress'
const DELIVERY_RPC_UPLOAD_EVIDENCE = 'rpc_delivery_upload_evidence'
const DELIVERY_RPC_RETRY_EVIDENCE = 'rpc_delivery_retry_evidence'
const DELIVERY_RPC_SUBMIT_EXCEPTION = 'rpc_delivery_submit_exception'
const DELIVERY_RPC_FINISH_SERVICE = 'rpc_delivery_finish_service'
const DELIVERY_RPC_RECORD_LIST = 'rpc_delivery_record_list'
const DELIVERY_RPC_MESSAGE_LIST = 'rpc_delivery_message_list'
const DELIVERY_RPC_SET_ONLINE_STATUS = 'rpc_delivery_set_online_status'
const DELIVERY_MOCK_PROFILE_KEY = 'delivery_mock_profile'
const DELIVERY_MOCK_ORDERS_KEY = 'delivery_mock_orders'
const DELIVERY_FORCE_REMOTE_KEY = 'delivery_force_remote'

const missingDeliveryRpcNames = [] as Array<string>

function isMissingDeliveryRpc(functionName: string): boolean {
	for (let i = 0; i < missingDeliveryRpcNames.length; i++) {
		if (missingDeliveryRpcNames[i] == functionName) {
			return true
		}
	}
	return false
}

function markMissingDeliveryRpc(functionName: string): void {
	if (!isMissingDeliveryRpc(functionName)) {
		missingDeliveryRpcNames.push(functionName)
	}
}

function mapLoginError(rawData: UTSJSONObject): string {
	const errorMsg = rawData.getString('msg') ?? rawData.getString('message') ?? rawData.getString('error') ?? ''
	const errorCode = rawData.getString('error_code') ?? ''
	if ((errorMsg.includes('email') && errorMsg.includes('confirm')) || errorCode === 'email_not_confirmed' || (errorMsg.includes('邮箱') && errorMsg.includes('确认'))) {
		return '邮箱未确认，请先检查邮箱并点击确认链接'
	}
	if (errorMsg.includes('Invalid authentication credentials')) {
		return '网关认证失败，请检查 delivery 端的 SUPA_URL 与 SUPA_KEY 是否属于同一套 Supabase 实例'
	}
	if (errorMsg.includes('Invalid login credentials') || errorCode === 'invalid_credentials' || errorMsg.includes('Invalid credentials') || errorMsg.includes('credentials') || errorMsg.includes('invalid')) {
		return '用户名或密码错误'
	}
	return errorMsg != '' ? errorMsg : '登录失败，请重试'
}

function readObjectField(raw: any, key: string): any {
	if (raw == null) {
		return null
	}
	if (typeof raw.getJSONObject === 'function') {
		const nested = raw.getJSONObject(key)
		if (nested != null) {
			return nested
		}
	}
	try {
		const plain = JSON.parse(JSON.stringify(raw)) as any
		return plain[key]
	} catch (error) {}
	return null
}

function readStringField(raw: any, key: string): string {
	if (raw == null) {
		return ''
	}
	if (typeof raw.getString === 'function') {
		return raw.getString(key) ?? ''
	}
	try {
		const plain = JSON.parse(JSON.stringify(raw)) as any
		const value = plain[key]
		if (typeof value == 'string') {
			return value
		}
		if (value != null) {
			return String(value)
		}
	} catch (error) {}
	return ''
}

function readNumberField(raw: any, key: string): number | null {
	if (raw == null) {
		return null
	}
	if (typeof raw.getNumber === 'function') {
		return raw.getNumber(key)
	}
	try {
		const plain = JSON.parse(JSON.stringify(raw)) as any
		const value = plain[key]
		if (typeof value == 'number') {
			return value
		}
	} catch (error) {}
	return null
}

function readBooleanField(raw: any, key: string): boolean | null {
	if (raw == null) {
		return null
	}
	if (typeof raw.getBoolean === 'function') {
		return raw.getBoolean(key)
	}
	try {
		const plain = JSON.parse(JSON.stringify(raw)) as any
		const value = plain[key]
		if (typeof value == 'boolean') {
			return value
		}
	} catch (error) {}
	return null
}

function normalizeDeliveryStatus(raw: any): 'active' | 'disabled' | 'locked' | 'suspended' {
	const status = readNumberField(raw, 'status')
	const isActive = readBooleanField(raw, 'is_active')
	if (status === 0 || isActive === false) {
		return 'disabled'
	}
	return 'active'
}

function normalizeOnlineStatus(raw: any): 'online' | 'resting' | 'busy' {
	const value = readStringField(raw, 'online_status')
	if (value == 'online' || value == 'busy') {
		return value
	}
	return 'resting'
}

function normalizeCertificateStatus(raw: any): 'valid' | 'expired' | 'pending' {
	const value = readStringField(raw, 'certificate_status')
	if (value == 'valid' || value == 'expired') {
		return value
	}
	return 'pending'
}

function normalizeStringArray(rawValue: string): Array<string> {
	const value = rawValue.trim()
	if (value == '') {
		return [] as Array<string>
	}
	try {
		const parsed = JSON.parse(value)
		if (parsed instanceof Array) {
			const result = [] as Array<string>
			for (let i = 0; i < parsed.length; i++) {
				const item = parsed[i]
				if (typeof item == 'string') {
					result.push(item)
				}
			}
			return result
		}
	} catch (error) {}
	return [] as Array<string>
}

function readStationObject(raw: any): any {
	const station = readObjectField(raw, 'station')
	if (station != null) {
		return station
	}
	const nested = readObjectField(raw, 'ml_delivery_stations')
	if (nested != null) {
		return nested
	}
	return null
}

function buildDeliveryInfoFromStaff(raw: any): DeliveryInfoType {
	const id = readStringField(raw, 'id')
	const station = readStationObject(raw)
	const stationId = readStringField(raw, 'station_id')
	const skillsRaw = readStringField(raw, 'skills')
	const certificateExpireAt = readStringField(raw, 'certificate_expire_at')
	const organizationName = station != null ? readStringField(station, 'name') : ''
	return {
		id,
		userId: readStringField(raw, 'uid'),
		staffNo: readStringField(raw, 'staff_no') != '' ? readStringField(raw, 'staff_no') : (id != '' ? 'DEL-' + id.substring(0, Math.min(8, id.length)).toUpperCase() : ''),
		name: readStringField(raw, 'nickname') != '' ? readStringField(raw, 'nickname') : '服务人员',
		phone: readStringField(raw, 'phone'),
		role: 'delivery',
		status: normalizeDeliveryStatus(raw),
		organizationId: stationId,
		organizationName: organizationName != '' ? organizationName : stationId,
		certificates: [] as Array<any>,
		certificateStatus: normalizeCertificateStatus(raw),
		certificateExpireAt,
		onlineStatus: normalizeOnlineStatus(raw),
		serviceArea: readStringField(raw, 'service_area'),
		skills: normalizeStringArray(skillsRaw),
		avatarUrl: readStringField(raw, 'avatar'),
		todayAccepted: 0,
		todayServing: 0,
		todayCompleted: 0,
		usesMock: false
	} as DeliveryInfoType
}

async function fetchDeliveryProfileFromRemote(userId: string): Promise<DeliveryInfoType | null> {
	if (userId == '') {
		return null
	}
	const selectFields = '*, station:ml_delivery_stations(id, name)'
	try {
		let response = await supa.from('ml_delivery_staff').select(selectFields).eq('uid', userId).limit(1).execute()
		if (response.error == null && response.data != null) {
			const rows = response.data as Array<UTSJSONObject>
			if (rows.length > 0) {
				return buildDeliveryInfoFromStaff(rows[0])
			}
		}

		response = await supa.from('ml_delivery_staff').select(selectFields).eq('id', userId).limit(1).execute()
		if (response.error == null && response.data != null) {
			const rows = response.data as Array<UTSJSONObject>
			if (rows.length > 0) {
				return buildDeliveryInfoFromStaff(rows[0])
			}
		}
	} catch (error) {
		console.warn('[delivery api] 读取 ml_delivery_staff 失败，回退 mock：', error)
	}
	return null
}

function isDelivererRole(userInfo: UserProfile | null): boolean {
	if (userInfo == null) {
		return false
	}
	const role = userInfo.role ?? ''
	return role == 'delivery' || role == 'Deliverer'
}

function shouldBypassDeliveryRpc(): boolean {
	if (IS_TEST_MODE !== true) {
		return false
	}
	const forceRemote = uni.getStorageSync(DELIVERY_FORCE_REMOTE_KEY)
	if (forceRemote === true) {
		return false
	}
	if (typeof forceRemote == 'string' && (forceRemote == 'true' || forceRemote == '1')) {
		return false
	}
	return true
}

async function callDeliveryRpc(functionName: string, params: UTSJSONObject): Promise<any> {
	if (shouldBypassDeliveryRpc()) {
		return null
	}
	if (isMissingDeliveryRpc(functionName)) {
		return null
	}
	try {
		await ensureSupabaseReady()
		const res: any = await supa.rpc(functionName, params)
		if (res?.status === 404) {
			markMissingDeliveryRpc(functionName)
			console.warn('[delivery api] RPC 不存在，已切换 fallback：' + functionName)
			return null
		}
		if (res?.error != null) {
			throw res.error
		}
		return res.data
	} catch (error) {
		console.warn('[delivery api] RPC 调用失败，回退 mock：' + functionName, error)
		return null
	}
}

function normalizeRpcOrderList(data: any): Array<DeliveryOrderType> | null {
	if (!Array.isArray(data)) {
		return null
	}
	return data as Array<DeliveryOrderType>
}

function normalizeRpcMessages(data: any): Array<DeliveryMessageType> | null {
	if (!Array.isArray(data)) {
		return null
	}
	return data as Array<DeliveryMessageType>
}

function normalizeRpcRecords(data: any): Array<DeliveryRecordType> | null {
	if (!Array.isArray(data)) {
		return null
	}
	return data as Array<DeliveryRecordType>
}

function normalizeRpcEvidenceList(data: any): Array<DeliveryEvidenceRecordType> | null {
	if (!Array.isArray(data)) {
		return null
	}
	return data as Array<DeliveryEvidenceRecordType>
}

function normalizeRpcOrder(data: any): DeliveryOrderType | null {
	if (data == null) {
		return null
	}
	return data as DeliveryOrderType
}

function normalizeRpcDashboard(data: any): DeliveryDashboardType | null {
	if (data == null) {
		return null
	}
	return data as DeliveryDashboardType
}

function normalizeRpcDeliveryInfo(data: any): DeliveryInfoType | null {
	if (data == null) {
		return null
	}
	return data as DeliveryInfoType
}

function cloneDeliveryInfo(info: DeliveryInfoType): DeliveryInfoType {
	return JSON.parse(JSON.stringify(info)) as DeliveryInfoType
}

function cloneDeliveryOrders(orders: Array<DeliveryOrderType>): Array<DeliveryOrderType> {
	return JSON.parse(JSON.stringify(orders)) as Array<DeliveryOrderType>
}

function cloneDeliveryOrder(order: DeliveryOrderType): DeliveryOrderType {
	return JSON.parse(JSON.stringify(order)) as DeliveryOrderType
}

function cloneDeliveryMessages(messages: Array<DeliveryMessageType>): Array<DeliveryMessageType> {
	return JSON.parse(JSON.stringify(messages)) as Array<DeliveryMessageType>
}

function cloneDeliveryRecords(records: Array<DeliveryRecordType>): Array<DeliveryRecordType> {
	return JSON.parse(JSON.stringify(records)) as Array<DeliveryRecordType>
}

function isObjectLike(value: any): boolean {
	return value != null && typeof value == 'object'
}

function isValidDeliveryInfoCache(value: any): boolean {
	if (!isObjectLike(value)) {
		return false
	}
	const info = value as DeliveryInfoType
	return typeof info.id == 'string' && typeof info.userId == 'string' && typeof info.name == 'string'
}

function isValidDeliveryOrdersCache(value: any): boolean {
	if (!Array.isArray(value)) {
		return false
	}
	for (let i = 0; i < value.length; i++) {
		const item = value[i] as any
		if (!isObjectLike(item) || typeof item.id != 'string' || typeof item.orderNo != 'string' || typeof item.status != 'string') {
			return false
		}
	}
	return true
}

function currentDateTimeText(): string {
	return new Date().toISOString().replace('T', ' ').substring(0, 19)
}

function buildMockCertificates(): Array<DeliveryCertificateType> {
	return [
		{
			id: 'mock-cert-1',
			name: '养老护理员职业技能证书',
			status: 'valid',
			expireAt: '2027-12-31',
			issuer: '梅州市居家养老服务协会',
			imageUrl: ''
		} as DeliveryCertificateType,
		{
			id: 'mock-cert-2',
			name: '慢病随访服务培训合格证',
			status: 'valid',
			expireAt: '长期有效',
			issuer: '粤东健康照护培训中心',
			imageUrl: ''
		} as DeliveryCertificateType
	] as Array<DeliveryCertificateType>
}

function buildMockServiceItems(orderId: string, serviceName: string): Array<DeliveryServiceItemType> {
	return [
		{
			id: orderId + '-item-1',
			name: serviceName + '签到核验',
			required: true,
			completed: true,
			incompleteReason: '',
			remark: '已完成身份核验与入户风险提示。',
			updatedAt: '2026-05-18 08:45:00'
		} as DeliveryServiceItemType,
		{
			id: orderId + '-item-2',
			name: '生命体征记录',
			required: true,
			completed: true,
			incompleteReason: '',
			remark: '血压、脉搏、血氧记录完整。',
			updatedAt: '2026-05-18 09:10:00'
		} as DeliveryServiceItemType,
		{
			id: orderId + '-item-3',
			name: '家属沟通与宣教',
			required: true,
			completed: false,
			incompleteReason: '',
			remark: '',
			updatedAt: ''
		} as DeliveryServiceItemType
	] as Array<DeliveryServiceItemType>
}

function buildMockTimeline(orderNo: string, phase: string): Array<DeliveryTimelineItemType> {
	return [
		{
			id: orderNo + '-tl-1',
			title: '工单已生成',
			time: '2026-05-18 07:30:00',
			description: '系统已创建服务任务并进入调度流程。'
		} as DeliveryTimelineItemType,
		{
			id: orderNo + '-tl-2',
			title: '调度已派发',
			time: '2026-05-18 07:50:00',
			description: '工单已分配至当前服务人员。'
		} as DeliveryTimelineItemType,
		{
			id: orderNo + '-tl-3',
			title: phase,
			time: '2026-05-18 08:20:00',
			description: '当前环节已进入执行节点。'
		} as DeliveryTimelineItemType
	] as Array<DeliveryTimelineItemType>
}

function buildMockEvidence(orderId: string): Array<DeliveryEvidenceRecordType> {
	return [
		{
			id: orderId + '-evi-1',
			orderId,
			phase: 'checkin',
			fileType: 'image',
			name: '到场签到照片',
			url: '',
			localPath: '/static/mock/checkin-' + orderId + '.jpg',
			status: 'success',
			progress: 100,
			retryable: false,
			createdAt: '2026-05-18 08:42:00'
		} as DeliveryEvidenceRecordType
	] as Array<DeliveryEvidenceRecordType>
}

function buildMockProfile(userId: string): DeliveryInfoType {
	const resolvedUserId = userId != '' ? userId : 'mock-user-delivery-001'
	return {
		id: 'mock-staff-001',
		userId: resolvedUserId,
		staffNo: 'DEL-0520',
		name: '陈护理',
		phone: '13688886666',
		role: 'delivery',
		status: 'active',
		organizationId: 'org-001',
		organizationName: '梅州安康居家服务中心',
		certificates: buildMockCertificates(),
		certificateStatus: 'valid',
		certificateExpireAt: '2027-12-31',
		onlineStatus: 'online',
		serviceArea: '梅江区 / 梅县区重点片区',
		skills: ['基础护理', '慢病随访', '康复指导'],
		avatarUrl: '',
		todayAccepted: 0,
		todayServing: 0,
		todayCompleted: 0,
		usesMock: true
	} as DeliveryInfoType
}

function buildMockOrders(profile: DeliveryInfoType): Array<DeliveryOrderType> {
	return [
		{
			id: 'mock-order-001',
			orderNo: 'YS202605180001',
			serviceType: '基础照护',
			serviceName: '基础上门护理',
			serviceItems: buildMockServiceItems('mock-order-001', '基础上门护理'),
			elderId: 'elder-001',
			elderNameMasked: '李奶奶',
			elderPhoneMasked: '138****1024',
			fullElderName: '李秀珍',
			fullPhone: '13800131024',
			addressSummary: '梅江区江南路 18 号 2 栋 602',
			fullAddress: '广东省梅州市梅江区江南路 18 号 2 栋 602 室',
			latitude: 24.2898,
			longitude: 116.1179,
			appointmentStartTime: '2026-05-18 09:00',
			appointmentEndTime: '2026-05-18 11:00',
			estimatedDuration: 120,
			actualStartTime: '',
			actualEndTime: '',
			status: 'pending_accept',
			statusText: '待接单',
			statusTone: 'warning',
			riskTags: ['跌倒风险', '晨间血压波动'],
			careLevel: '护理二级',
			merchantId: 'merchant-001',
			merchantName: '梅州安康居家服务中心',
			deliveryStaffId: profile.id,
			deliveryStaffName: profile.name,
			acceptTime: '',
			departTime: '',
			arriveTime: '',
			checkinTime: '',
			finishTime: '',
			cancelReason: '',
			exceptionType: '',
			exceptionDesc: '',
			evidenceList: [] as Array<DeliveryEvidenceRecordType>,
			signatureUrl: '',
			signatureName: '',
			satisfactionStatus: '待评价',
			settlementStatus: '待结算',
			archiveStatus: '未归档',
			createdAt: '2026-05-18 07:30:00',
			updatedAt: '2026-05-18 07:50:00',
			contactName: '李晓兰',
			contactPhone: '13900139000',
			notices: ['入户前需电话确认', '注意老人步态不稳'],
			timeline: buildMockTimeline('YS202605180001', '等待服务人员接单'),
			serviceSummary: '',
			progressNote: '',
			distanceKm: '2.4km',
			allowCheckinRadiusMeters: 100,
			lastLocation: null,
			trackPoints: [] as Array<DeliveryLocationType>
		} as DeliveryOrderType,
		{
			id: 'mock-order-002',
			orderNo: 'YS202605180002',
			serviceType: '康复指导',
			serviceName: '居家康复训练指导',
			serviceItems: buildMockServiceItems('mock-order-002', '康复训练'),
			elderId: 'elder-002',
			elderNameMasked: '张爷爷',
			elderPhoneMasked: '137****2233',
			fullElderName: '张志坤',
			fullPhone: '13700132233',
			addressSummary: '梅县区新城锦绣花园 5 栋 1403',
			fullAddress: '广东省梅州市梅县区新城锦绣花园 5 栋 1403 室',
			latitude: 24.3071,
			longitude: 116.1365,
			appointmentStartTime: '2026-05-18 10:30',
			appointmentEndTime: '2026-05-18 12:00',
			estimatedDuration: 90,
			actualStartTime: '',
			actualEndTime: '',
			status: 'accepted',
			statusText: '待出发',
			statusTone: 'primary',
			riskTags: ['术后恢复'],
			careLevel: '康复随访',
			merchantId: 'merchant-001',
			merchantName: '梅州安康居家服务中心',
			deliveryStaffId: profile.id,
			deliveryStaffName: profile.name,
			acceptTime: '2026-05-18 08:00:00',
			departTime: '',
			arriveTime: '',
			checkinTime: '',
			finishTime: '',
			cancelReason: '',
			exceptionType: '',
			exceptionDesc: '',
			evidenceList: [] as Array<DeliveryEvidenceRecordType>,
			signatureUrl: '',
			signatureName: '',
			satisfactionStatus: '待评价',
			settlementStatus: '待结算',
			archiveStatus: '未归档',
			createdAt: '2026-05-18 07:40:00',
			updatedAt: '2026-05-18 08:00:00',
			contactName: '张春梅',
			contactPhone: '13600136666',
			notices: ['需携带康复弹力带', '家属会同步在场'],
			timeline: buildMockTimeline('YS202605180002', '已接单，等待出发'),
			serviceSummary: '',
			progressNote: '',
			distanceKm: '5.8km',
			allowCheckinRadiusMeters: 120,
			lastLocation: null,
			trackPoints: [] as Array<DeliveryLocationType>
		} as DeliveryOrderType,
		{
			id: 'mock-order-003',
			orderNo: 'YS202605180003',
			serviceType: '慢病随访',
			serviceName: '慢病健康随访',
			serviceItems: buildMockServiceItems('mock-order-003', '慢病随访'),
			elderId: 'elder-003',
			elderNameMasked: '黄阿姨',
			elderPhoneMasked: '135****5566',
			fullElderName: '黄玉英',
			fullPhone: '13500135566',
			addressSummary: '梅江区学海路康养公寓 A 座 907',
			fullAddress: '广东省梅州市梅江区学海路康养公寓 A 座 907 室',
			latitude: 24.2861,
			longitude: 116.1231,
			appointmentStartTime: '2026-05-18 13:30',
			appointmentEndTime: '2026-05-18 15:00',
			estimatedDuration: 90,
			actualStartTime: '',
			actualEndTime: '',
			status: 'arrived',
			statusText: '待签到',
			statusTone: 'primary',
			riskTags: ['糖尿病', '需测血糖'],
			careLevel: '慢病管理',
			merchantId: 'merchant-001',
			merchantName: '梅州安康居家服务中心',
			deliveryStaffId: profile.id,
			deliveryStaffName: profile.name,
			acceptTime: '2026-05-18 08:10:00',
			departTime: '2026-05-18 13:00:00',
			arriveTime: '2026-05-18 13:22:00',
			checkinTime: '',
			finishTime: '',
			cancelReason: '',
			exceptionType: '',
			exceptionDesc: '',
			evidenceList: [] as Array<DeliveryEvidenceRecordType>,
			signatureUrl: '',
			signatureName: '',
			satisfactionStatus: '待评价',
			settlementStatus: '待结算',
			archiveStatus: '未归档',
			createdAt: '2026-05-18 08:00:00',
			updatedAt: '2026-05-18 13:22:00',
			contactName: '黄晓娟',
			contactPhone: '13500130088',
			notices: ['入户前请确认血糖试纸数量', '注意老人午后低血糖风险'],
			timeline: buildMockTimeline('YS202605180003', '已到达服务地点'),
			serviceSummary: '',
			progressNote: '已联系家属，准备入户签到。',
			distanceKm: '1.1km',
			allowCheckinRadiusMeters: 80,
			lastLocation: {
				latitude: 24.2861,
				longitude: 116.1231,
				address: '康养公寓门口',
				time: '2026-05-18 13:22:00'
			} as DeliveryLocationType,
			trackPoints: [] as Array<DeliveryLocationType>
		} as DeliveryOrderType,
		{
			id: 'mock-order-004',
			orderNo: 'YS202605180004',
			serviceType: '居家护理',
			serviceName: '压疮护理与翻身指导',
			serviceItems: [
				{
					id: 'mock-order-004-item-1',
					name: '压疮护理',
					required: true,
					completed: true,
					incompleteReason: '',
					remark: '已完成创面清洁与敷料更换。',
					updatedAt: '2026-05-18 14:25:00'
				} as DeliveryServiceItemType,
				{
					id: 'mock-order-004-item-2',
					name: '翻身指导',
					required: true,
					completed: true,
					incompleteReason: '',
					remark: '已向家属示范翻身角度与频次。',
					updatedAt: '2026-05-18 14:40:00'
				} as DeliveryServiceItemType,
				{
					id: 'mock-order-004-item-3',
					name: '家属签字确认',
					required: true,
					completed: false,
					incompleteReason: '',
					remark: '',
					updatedAt: ''
				} as DeliveryServiceItemType
			] as Array<DeliveryServiceItemType>,
			elderId: 'elder-004',
			elderNameMasked: '陈伯伯',
			elderPhoneMasked: '139****3301',
			fullElderName: '陈国辉',
			fullPhone: '13900133301',
			addressSummary: '梅县区扶老社区 11 栋 203',
			fullAddress: '广东省梅州市梅县区扶老社区 11 栋 203 室',
			latitude: 24.3022,
			longitude: 116.1441,
			appointmentStartTime: '2026-05-18 14:00',
			appointmentEndTime: '2026-05-18 16:00',
			estimatedDuration: 120,
			actualStartTime: '2026-05-18 14:05:00',
			actualEndTime: '',
			status: 'serving',
			statusText: '服务中',
			statusTone: 'primary',
			riskTags: ['卧床护理', '家属需培训'],
			careLevel: '护理三级',
			merchantId: 'merchant-001',
			merchantName: '梅州安康居家服务中心',
			deliveryStaffId: profile.id,
			deliveryStaffName: profile.name,
			acceptTime: '2026-05-18 09:20:00',
			departTime: '2026-05-18 13:20:00',
			arriveTime: '2026-05-18 13:55:00',
			checkinTime: '2026-05-18 14:00:00',
			finishTime: '',
			cancelReason: '',
			exceptionType: '',
			exceptionDesc: '',
			evidenceList: buildMockEvidence('mock-order-004'),
			signatureUrl: '',
			signatureName: '',
			satisfactionStatus: '待评价',
			settlementStatus: '待结算',
			archiveStatus: '未归档',
			createdAt: '2026-05-18 09:00:00',
			updatedAt: '2026-05-18 14:40:00',
			contactName: '陈丽芳',
			contactPhone: '13800136660',
			notices: ['护理过程注意皮肤完整性', '家属需学习翻身技巧'],
			timeline: buildMockTimeline('YS202605180004', '服务执行中'),
			serviceSummary: '已完成基础护理与翻身指导，待家属签字确认。',
			progressNote: '创面情况稳定，已完成阶段性护理。',
			distanceKm: '3.6km',
			allowCheckinRadiusMeters: 100,
			lastLocation: {
				latitude: 24.3022,
				longitude: 116.1441,
				address: '扶老社区 11 栋 203 室',
				time: '2026-05-18 14:00:00'
			} as DeliveryLocationType,
			trackPoints: [
				{
					latitude: 24.3001,
					longitude: 116.1412,
					address: '扶老社区北门',
					time: '2026-05-18 13:48:00'
				} as DeliveryLocationType,
				{
					latitude: 24.3022,
					longitude: 116.1441,
					address: '扶老社区 11 栋 203 室',
					time: '2026-05-18 14:00:00'
				} as DeliveryLocationType
			] as Array<DeliveryLocationType>
		} as DeliveryOrderType,
		{
			id: 'mock-order-005',
			orderNo: 'YS202605180005',
			serviceType: '异常跟进',
			serviceName: '用药异常上报处理',
			serviceItems: buildMockServiceItems('mock-order-005', '异常处理'),
			elderId: 'elder-005',
			elderNameMasked: '王阿婆',
			elderPhoneMasked: '134****7744',
			fullElderName: '王月兰',
			fullPhone: '13400137744',
			addressSummary: '梅江区东汇城旁康颐楼 3 单元 1204',
			fullAddress: '广东省梅州市梅江区东汇城旁康颐楼 3 单元 1204 室',
			latitude: 24.2932,
			longitude: 116.1205,
			appointmentStartTime: '2026-05-18 16:00',
			appointmentEndTime: '2026-05-18 17:00',
			estimatedDuration: 60,
			actualStartTime: '2026-05-18 16:05:00',
			actualEndTime: '',
			status: 'exception_pending',
			statusText: '异常处理中',
			statusTone: 'warning',
			riskTags: ['用药异常', '需医生回访'],
			careLevel: '异常处置',
			merchantId: 'merchant-001',
			merchantName: '梅州安康居家服务中心',
			deliveryStaffId: profile.id,
			deliveryStaffName: profile.name,
			acceptTime: '2026-05-18 15:20:00',
			departTime: '2026-05-18 15:35:00',
			arriveTime: '2026-05-18 15:58:00',
			checkinTime: '2026-05-18 16:03:00',
			finishTime: '',
			cancelReason: '',
			exceptionType: 'elder_health_abnormal',
			exceptionDesc: '老人午后血压异常升高，已建议暂停训练并等待医生回访。',
			evidenceList: buildMockEvidence('mock-order-005'),
			signatureUrl: '',
			signatureName: '',
			satisfactionStatus: '待处理',
			settlementStatus: '待确认',
			archiveStatus: '未归档',
			createdAt: '2026-05-18 15:00:00',
			updatedAt: '2026-05-18 16:10:00',
			contactName: '王秀玲',
			contactPhone: '13600139922',
			notices: ['优先联系家属', '记录老人异常表现并上传照片'],
			timeline: buildMockTimeline('YS202605180005', '异常已上报，等待处理'),
			serviceSummary: '发现老人血压异常升高，已完成初步安抚并联系家属。',
			progressNote: '异常已同步机构值班护士。',
			distanceKm: '4.2km',
			allowCheckinRadiusMeters: 100,
			lastLocation: {
				latitude: 24.2932,
				longitude: 116.1205,
				address: '康颐楼 3 单元 1204 室',
				time: '2026-05-18 16:03:00'
			} as DeliveryLocationType,
			trackPoints: [] as Array<DeliveryLocationType>
		} as DeliveryOrderType,
		{
			id: 'mock-order-006',
			orderNo: 'YS202605170006',
			serviceType: '康复护理',
			serviceName: '术后恢复陪护',
			serviceItems: [
				{
					id: 'mock-order-006-item-1',
					name: '步态训练',
					required: true,
					completed: true,
					incompleteReason: '',
					remark: '完成 15 分钟辅助行走训练。',
					updatedAt: '2026-05-17 15:10:00'
				} as DeliveryServiceItemType,
				{
					id: 'mock-order-006-item-2',
					name: '术后注意事项宣教',
					required: true,
					completed: true,
					incompleteReason: '',
					remark: '已向家属说明饮食与休息要求。',
					updatedAt: '2026-05-17 15:28:00'
				} as DeliveryServiceItemType
			] as Array<DeliveryServiceItemType>,
			elderId: 'elder-006',
			elderNameMasked: '刘叔叔',
			elderPhoneMasked: '133****6655',
			fullElderName: '刘建华',
			fullPhone: '13300136655',
			addressSummary: '梅江区和顺苑 9 栋 401',
			fullAddress: '广东省梅州市梅江区和顺苑 9 栋 401 室',
			latitude: 24.2806,
			longitude: 116.1115,
			appointmentStartTime: '2026-05-17 14:00',
			appointmentEndTime: '2026-05-17 15:30',
			estimatedDuration: 90,
			actualStartTime: '2026-05-17 14:05:00',
			actualEndTime: '2026-05-17 15:32:00',
			status: 'completed',
			statusText: '已完成',
			statusTone: 'success',
			riskTags: ['术后恢复'],
			careLevel: '康复照护',
			merchantId: 'merchant-001',
			merchantName: '梅州安康居家服务中心',
			deliveryStaffId: profile.id,
			deliveryStaffName: profile.name,
			acceptTime: '2026-05-17 12:40:00',
			departTime: '2026-05-17 13:20:00',
			arriveTime: '2026-05-17 13:55:00',
			checkinTime: '2026-05-17 14:00:00',
			finishTime: '2026-05-17 15:32:00',
			cancelReason: '',
			exceptionType: '',
			exceptionDesc: '',
			evidenceList: buildMockEvidence('mock-order-006'),
			signatureUrl: '',
			signatureName: '刘建华',
			satisfactionStatus: '已评价',
			settlementStatus: '已结算',
			archiveStatus: '已归档',
			createdAt: '2026-05-17 12:20:00',
			updatedAt: '2026-05-17 15:32:00',
			contactName: '刘晓芳',
			contactPhone: '13800132299',
			notices: ['术后行动缓慢，注意搀扶'],
			timeline: buildMockTimeline('YS202605170006', '服务完成待回访'),
			serviceSummary: '术后恢复训练顺利完成，家属已确认并签字。',
			progressNote: '服务完成，建议两日后再次回访。',
			distanceKm: '6.1km',
			allowCheckinRadiusMeters: 100,
			lastLocation: {
				latitude: 24.2806,
				longitude: 116.1115,
				address: '和顺苑 9 栋 401 室',
				time: '2026-05-17 15:32:00'
			} as DeliveryLocationType,
			trackPoints: [] as Array<DeliveryLocationType>
		} as DeliveryOrderType
	] as Array<DeliveryOrderType>
}

function readMockDeliveryInfo(): DeliveryInfoType | null {
	const cached = uni.getStorageSync(DELIVERY_MOCK_PROFILE_KEY)
	if (!isValidDeliveryInfoCache(cached)) {
		return null
	}
	return cached as DeliveryInfoType
}

function persistMockDeliveryInfo(info: DeliveryInfoType): void {
	uni.setStorageSync(DELIVERY_MOCK_PROFILE_KEY, cloneDeliveryInfo(info))
}

function readMockOrders(): Array<DeliveryOrderType> | null {
	const cached = uni.getStorageSync(DELIVERY_MOCK_ORDERS_KEY)
	if (!isValidDeliveryOrdersCache(cached)) {
		return null
	}
	return cached as Array<DeliveryOrderType>
}

function persistMockOrders(orders: Array<DeliveryOrderType>): void {
	uni.setStorageSync(DELIVERY_MOCK_ORDERS_KEY, cloneDeliveryOrders(orders))
}

function ensureMockProfile(userId: string): DeliveryInfoType {
	const cached = readMockDeliveryInfo()
	if (cached != null) {
		if (cached.userId == '' && userId != '') {
			cached.userId = userId
			persistMockDeliveryInfo(cached)
		}
		return cached
	}
	const profile = buildMockProfile(userId)
	persistMockDeliveryInfo(profile)
	return profile
}

function ensureMockOrders(userId: string): Array<DeliveryOrderType> {
	const cached = readMockOrders()
	if (cached != null && cached.length > 0) {
		return cached
	}
	const profile = ensureMockProfile(userId)
	const orders = buildMockOrders(profile)
	persistMockOrders(orders)
	return orders
}

function isPendingDepartStatus(status: string): boolean {
	return status == 'accepted' || status == 'on_the_way' || status == 'arrived'
}

function isServingStatus(status: string): boolean {
	return status == 'checked_in' || status == 'serving' || status == 'pending_submit' || status == 'pending_acceptance'
}

function isCompletedStatus(status: string): boolean {
	return status == 'completed' || status == 'settled' || status == 'archived'
}

function buildMockProfileWithStats(userId: string): DeliveryInfoType {
	const profile = cloneDeliveryInfo(ensureMockProfile(userId))
	const orders = ensureMockOrders(userId)
	let acceptedCount = 0
	let servingCount = 0
	let completedCount = 0
	for (let i = 0; i < orders.length; i++) {
		if (orders[i].acceptTime != '') {
			acceptedCount++
		}
		if (isServingStatus(orders[i].status)) {
			servingCount++
		}
		if (isCompletedStatus(orders[i].status)) {
			completedCount++
		}
	}
	profile.todayAccepted = acceptedCount
	profile.todayServing = servingCount
	profile.todayCompleted = completedCount
	profile.usesMock = true
	return profile
}

function buildMockMessages(orders: Array<DeliveryOrderType>): Array<DeliveryMessageType> {
	return [
		{
			id: 'mock-msg-1',
			title: '新工单待接单',
			content: '基础照护 · 基础上门护理已分配给你，服务对象：李奶奶，预约时间：2026-05-18 09:00，请及时确认接单并做好上门准备。',
			type: 'order',
			createdAt: '2026-05-18 08:20',
			read: false,
			orderId: orders[0].id
		} as DeliveryMessageType,
		{
			id: 'mock-msg-2',
			title: '出发提醒',
			content: '康复指导 · 居家康复训练指导将在 30 分钟后开始，服务地址：梅县区新城锦绣花园 5 栋 1403，请提前规划路线并按时出发。',
			type: 'reminder',
			createdAt: '2026-05-18 10:00',
			read: false,
			orderId: orders[1].id
		} as DeliveryMessageType,
		{
			id: 'mock-msg-3',
			title: '异常处理提醒',
			content: '慢病随访工单出现异常：当前暂时无法联系服务对象，请尽快查看工单详情并提交处理结果。',
			type: 'exception',
			createdAt: '2026-05-18 10:35',
			read: false,
			orderId: orders[4].id
		} as DeliveryMessageType,
		{
			id: 'mock-msg-4',
			title: '工单改派通知',
			content: '平台已将“陪诊协助 · 复诊陪同”改派给你，预约时间：2026-05-18 14:30，请及时查看服务要求与上门信息。',
			type: 'dispatch',
			createdAt: '2026-05-18 11:10',
			read: false,
			orderId: orders[3].id
		} as DeliveryMessageType,
		{
			id: 'mock-msg-5',
			title: '签到提醒',
			content: '你已接近服务地点，请在到达后完成签到，签到成功后即可开始服务记录。',
			type: 'checkin',
			createdAt: '2026-05-18 13:20',
			read: true,
			orderId: orders[2].id
		} as DeliveryMessageType,
		{
			id: 'mock-msg-6',
			title: '服务验收通过',
			content: '基础照护工单已完成验收，服务对象家属已确认本次服务，相关记录已同步更新。',
			type: 'result',
			createdAt: '2026-05-17 18:40',
			read: true,
			orderId: orders[5].id
		} as DeliveryMessageType,
		{
			id: 'mock-msg-7',
			title: '结算通知',
			content: '昨日完成的 3 个服务工单已进入结算流程，请在“我的-服务记录”中查看结算进度。',
			type: 'settlement',
			createdAt: '2026-05-17 09:15',
			read: true,
			orderId: ''
		} as DeliveryMessageType,
		{
			id: 'mock-msg-8',
			title: '系统公告',
			content: '请服务人员上门前核对服务对象信息，服务过程中注意留痕记录，并按规范完成异常上报。',
			type: 'notice',
			createdAt: '2026-05-16 16:00',
			read: true,
			orderId: ''
		} as DeliveryMessageType
	] as Array<DeliveryMessageType>
}

function buildMockRecords(orders: Array<DeliveryOrderType>): Array<DeliveryRecordType> {
	const result = [] as Array<DeliveryRecordType>
	for (let i = 0; i < orders.length; i++) {
		const item = orders[i]
		if (isCompletedStatus(item.status) || item.status == 'exception_pending') {
			result.push({
				id: 'record-' + item.id,
				orderId: item.id,
				orderNo: item.orderNo,
				serviceName: item.serviceName,
				elderNameMasked: item.elderNameMasked,
				status: item.status,
				statusText: item.statusText,
				appointmentStartTime: item.appointmentStartTime,
				actualStartTime: item.actualStartTime,
				actualEndTime: item.actualEndTime != '' ? item.actualEndTime : item.updatedAt,
				settlementStatus: item.settlementStatus,
				acceptanceStatus: item.satisfactionStatus,
				exceptionDesc: item.exceptionDesc,
				ratingText: item.status == 'completed' ? '五星好评' : '待补充说明'
			} as DeliveryRecordType)
		}
	}
	return result
}

function findMockOrderIndex(orders: Array<DeliveryOrderType>, orderId: string): number {
	for (let i = 0; i < orders.length; i++) {
		if (orders[i].id == orderId) {
			return i
		}
	}
	return -1
}

function sortMockRecentOrders(orders: Array<DeliveryOrderType>): Array<DeliveryOrderType> {
	const pendingException = [] as Array<DeliveryOrderType>
	const actionable = [] as Array<DeliveryOrderType>
	const completed = [] as Array<DeliveryOrderType>
	for (let i = 0; i < orders.length; i++) {
		const item = orders[i]
		if (item.status == 'exception_pending') {
			pendingException.push(item)
		} else if (!isCompletedStatus(item.status)) {
			actionable.push(item)
		} else {
			completed.push(item)
		}
	}
	return pendingException.concat(actionable).concat(completed)
}

function filterMockOrders(orders: Array<DeliveryOrderType>, query: DeliveryOrderQueryType): Array<DeliveryOrderType> {
	const keyword = query.keyword.trim()
	const result = [] as Array<DeliveryOrderType>
	for (let i = 0; i < orders.length; i++) {
		const item = orders[i]
		let tabMatched = false
		if (query.tab == 'all' || query.tab == '') {
			tabMatched = true
		} else if (query.tab == 'pending_accept') {
			tabMatched = item.status == 'pending_accept'
		} else if (query.tab == 'accepted') {
			tabMatched = isPendingDepartStatus(item.status)
		} else if (query.tab == 'serving') {
			tabMatched = isServingStatus(item.status)
		} else if (query.tab == 'pending_submit') {
			tabMatched = item.status == 'pending_submit' || item.status == 'pending_acceptance'
		} else if (query.tab == 'completed') {
			tabMatched = isCompletedStatus(item.status)
		} else if (query.tab == 'exception') {
			tabMatched = item.status == 'exception_pending'
		}
		if (!tabMatched) {
			continue
		}
		if (keyword != '') {
			const matched = item.orderNo.includes(keyword) || item.serviceName.includes(keyword) || item.elderNameMasked.includes(keyword) || item.addressSummary.includes(keyword)
			if (!matched) {
				continue
			}
		}
		result.push(cloneDeliveryOrder(item))
	}
	return result
}

function readCachedDeliveryInfo(userId: string): DeliveryInfoType | null {
	const cached = uni.getStorageSync('delivery_info')
	if (!isValidDeliveryInfoCache(cached)) {
		return null
	}
	const info = cached as DeliveryInfoType
	if (userId == '' || info.userId == userId || info.id == userId) {
		return info
	}
	return null
}

async function fallbackGetDeliveryProfileByUserId(userId: string): Promise<DeliveryInfoType | null> {
	const cached = readCachedDeliveryInfo(userId)
	if (cached != null) {
		return cached
	}
	return buildMockProfileWithStats(userId)
}

async function fallbackGetDashboard(staffId: string): Promise<DeliveryDashboardType> {
	const profile = buildMockProfileWithStats(staffId)
	const orders = ensureMockOrders(staffId)
	let pendingAcceptCount = 0
	let pendingDepartCount = 0
	let servingCount = 0
	let completedCount = 0
	let exceptionCount = 0
	for (let i = 0; i < orders.length; i++) {
		const status = orders[i].status
		if (status == 'pending_accept') {
			pendingAcceptCount++
		} else if (isPendingDepartStatus(status)) {
			pendingDepartCount++
		} else if (isServingStatus(status)) {
			servingCount++
		} else if (status == 'exception_pending') {
			exceptionCount++
		} else if (isCompletedStatus(status)) {
			completedCount++
		}
	}
	return {
		pendingAcceptCount,
		pendingDepartCount,
		servingCount,
		completedCount,
		exceptionCount,
		onlineStatus: profile.onlineStatus,
		recentOrders: sortMockRecentOrders(cloneDeliveryOrders(orders)).slice(0, 5) as Array<DeliveryOrderType>
	} as DeliveryDashboardType
}

async function fallbackGetOrders(staffId: string, query: DeliveryOrderQueryType): Promise<Array<DeliveryOrderType>> {
	const orders = ensureMockOrders(staffId)
	return filterMockOrders(orders, query)
}

async function fallbackGetOrderDetail(orderId: string): Promise<DeliveryOrderType | null> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return null
	}
	return cloneDeliveryOrder(orders[index])
}

async function fallbackAcceptOrder(orderId: string): Promise<DeliveryOrderType | null> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return null
	}
	orders[index].status = 'accepted'
	orders[index].statusText = '待出发'
	orders[index].statusTone = 'primary'
	orders[index].acceptTime = currentDateTimeText()
	orders[index].updatedAt = currentDateTimeText()
	orders[index].timeline.push({
		id: orders[index].orderNo + '-accepted',
		title: '服务人员已接单',
		time: orders[index].updatedAt,
		description: '已确认接单，待前往服务地点。'
	} as DeliveryTimelineItemType)
	persistMockOrders(orders)
	return cloneDeliveryOrder(orders[index])
}

async function fallbackRejectOrder(orderId: string, _reason: string): Promise<DeliveryOrderType | null> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return null
	}
	orders[index].status = 'cancelled'
	orders[index].statusText = '已取消'
	orders[index].statusTone = 'neutral'
	orders[index].updatedAt = currentDateTimeText()
	persistMockOrders(orders)
	return cloneDeliveryOrder(orders[index])
}

async function fallbackStartDepart(orderId: string, _location: DeliveryLocationType): Promise<DeliveryOrderType | null> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return null
	}
	orders[index].status = 'on_the_way'
	orders[index].statusText = '前往服务中'
	orders[index].statusTone = 'primary'
	orders[index].departTime = currentDateTimeText()
	orders[index].updatedAt = orders[index].departTime
	persistMockOrders(orders)
	return cloneDeliveryOrder(orders[index])
}

async function fallbackArriveOrder(orderId: string, _location: DeliveryLocationType): Promise<DeliveryOrderType | null> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return null
	}
	orders[index].status = 'arrived'
	orders[index].statusText = '待签到'
	orders[index].statusTone = 'primary'
	orders[index].arriveTime = currentDateTimeText()
	orders[index].updatedAt = orders[index].arriveTime
	persistMockOrders(orders)
	return cloneDeliveryOrder(orders[index])
}

async function fallbackCheckinOrder(orderId: string, payload: DeliveryCheckinPayloadType): Promise<DeliveryOrderType | null> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return null
	}
	orders[index].status = 'checked_in'
	orders[index].statusText = '已签到'
	orders[index].statusTone = 'primary'
	orders[index].checkinTime = currentDateTimeText()
	orders[index].updatedAt = orders[index].checkinTime
	orders[index].lastLocation = payload.location
	if (payload.photos.length > 0) {
		for (let i = 0; i < payload.photos.length; i++) {
			orders[index].evidenceList.push({
				id: orderId + '-checkin-photo-' + String(i + 1),
				orderId,
				phase: 'checkin',
				fileType: 'image',
				name: '签到照片' + String(i + 1),
				url: '',
				localPath: payload.photos[i],
				status: 'success',
				progress: 100,
				retryable: false,
				createdAt: currentDateTimeText()
			} as DeliveryEvidenceRecordType)
		}
	}
	persistMockOrders(orders)
	return cloneDeliveryOrder(orders[index])
}

async function fallbackStartService(orderId: string): Promise<DeliveryOrderType | null> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return null
	}
	orders[index].status = 'serving'
	orders[index].statusText = '服务中'
	orders[index].statusTone = 'primary'
	if (orders[index].actualStartTime == '') {
		orders[index].actualStartTime = currentDateTimeText()
	}
	orders[index].updatedAt = currentDateTimeText()
	persistMockOrders(orders)
	return cloneDeliveryOrder(orders[index])
}

async function fallbackSaveProgress(orderId: string, payload: DeliveryProgressPayloadType): Promise<DeliveryOrderType | null> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return null
	}
	orders[index].serviceItems = JSON.parse(JSON.stringify(payload.items)) as Array<DeliveryServiceItemType>
	orders[index].progressNote = payload.progressNote
	orders[index].serviceSummary = payload.serviceSummary
	orders[index].updatedAt = currentDateTimeText()
	persistMockOrders(orders)
	return cloneDeliveryOrder(orders[index])
}

async function fallbackUploadEvidence(orderId: string, phase: string, files: Array<string>): Promise<Array<DeliveryEvidenceRecordType>> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return [] as Array<DeliveryEvidenceRecordType>
	}
	const added = [] as Array<DeliveryEvidenceRecordType>
	for (let i = 0; i < files.length; i++) {
		const item = {
			id: orderId + '-evidence-' + String(orders[index].evidenceList.length + i + 1),
			orderId,
			phase,
			fileType: 'image',
			name: '服务留痕图片' + String(i + 1),
			url: '',
			localPath: files[i],
			status: 'success',
			progress: 100,
			retryable: false,
			createdAt: currentDateTimeText()
		} as DeliveryEvidenceRecordType
		orders[index].evidenceList.push(item)
		added.push(item)
	}
	orders[index].updatedAt = currentDateTimeText()
	persistMockOrders(orders)
	return JSON.parse(JSON.stringify(added)) as Array<DeliveryEvidenceRecordType>
}

async function fallbackRetryEvidence(orderId: string, evidenceId: string): Promise<DeliveryEvidenceRecordType | null> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return null
	}
	for (let i = 0; i < orders[index].evidenceList.length; i++) {
		if (orders[index].evidenceList[i].id == evidenceId) {
			orders[index].evidenceList[i].status = 'success'
			orders[index].evidenceList[i].progress = 100
			orders[index].evidenceList[i].retryable = false
			persistMockOrders(orders)
			return orders[index].evidenceList[i]
		}
	}
	return null
}

async function fallbackSubmitException(orderId: string, payload: DeliveryExceptionPayloadType): Promise<DeliveryOrderType | null> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return null
	}
	orders[index].status = 'exception_pending'
	orders[index].statusText = '异常处理中'
	orders[index].statusTone = 'warning'
	orders[index].exceptionType = payload.exceptionType
	orders[index].exceptionDesc = payload.description
	orders[index].updatedAt = currentDateTimeText()
	persistMockOrders(orders)
	return cloneDeliveryOrder(orders[index])
}

async function fallbackFinishService(orderId: string, payload: DeliveryFinishPayloadType): Promise<DeliveryOrderType | null> {
	const orders = ensureMockOrders('')
	const index = findMockOrderIndex(orders, orderId)
	if (index < 0) {
		return null
	}
	orders[index].status = 'completed'
	orders[index].statusText = '已完成'
	orders[index].statusTone = 'success'
	orders[index].serviceSummary = payload.serviceSummary
	orders[index].signatureName = payload.signatureName
	orders[index].actualEndTime = currentDateTimeText()
	orders[index].finishTime = orders[index].actualEndTime
	orders[index].satisfactionStatus = payload.confirmByFamily ? '待回访' : '待确认'
	orders[index].settlementStatus = '待结算'
	orders[index].archiveStatus = '待归档'
	orders[index].updatedAt = orders[index].actualEndTime
	persistMockOrders(orders)
	return cloneDeliveryOrder(orders[index])
}

async function fallbackGetRecords(staffId: string): Promise<Array<DeliveryRecordType>> {
	const orders = ensureMockOrders(staffId)
	return cloneDeliveryRecords(buildMockRecords(orders))
}

async function fallbackGetMessages(): Promise<Array<DeliveryMessageType>> {
	const orders = ensureMockOrders('')
	return cloneDeliveryMessages(buildMockMessages(orders))
}

async function fallbackUpdateOnlineStatus(staffId: string, status: string): Promise<DeliveryInfoType | null> {
	const cachedInfo = buildMockProfileWithStats(staffId)
	const nextInfo = {
		...cachedInfo,
		onlineStatus: status as 'online' | 'resting' | 'busy'
	} as DeliveryInfoType
	persistMockDeliveryInfo(nextInfo)
	return nextInfo
}

export async function loginDelivery(payload: DeliveryLoginPayloadType): Promise<DeliveryLoginResultType> {
	const account = payload.account.trim()
	if (!account.includes('@')) {
		throw new Error('请使用真实邮箱账号登录服务人员端')
	}

	const result = await supa.signIn(account, payload.password)
	if (result.user == null) {
		const rawData = result.raw as UTSJSONObject
		throw new Error(mapLoginError(rawData))
	}

	const profile = await getCurrentUser()
	if (profile == null || profile.id == null || profile.id == '') {
		try {
			await supa.signOut()
		} catch (error) {}
		throw new Error('登录状态已失效，请重新登录')
	}

	if (!isDelivererRole(profile)) {
		try {
			await supa.signOut()
		} catch (error) {}
		throw new Error('当前账号不是上门服务人员账号')
	}

	const deliveryInfo = await fetchDeliveryProfileFromRemote(profile.id)
	if (deliveryInfo == null) {
		try {
			await supa.signOut()
		} catch (error) {}
		throw new Error('当前账号未绑定服务人员档案')
	}

	return {
		token: result.access_token,
		userInfo: profile,
		deliveryInfo,
		usesMock: false
	}
}

export async function getDeliveryProfileByUserId(userId: string): Promise<DeliveryInfoType | null> {
	const remoteInfo = await fetchDeliveryProfileFromRemote(userId)
	if (remoteInfo != null) {
		return remoteInfo
	}
	return await fallbackGetDeliveryProfileByUserId(userId)
}

export async function getDeliveryDashboardByStaffId(staffId: string): Promise<DeliveryDashboardType> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_DASHBOARD, {
		p_staff_id: staffId
	} as UTSJSONObject)
	const dashboard = normalizeRpcDashboard(rpcData)
	if (dashboard != null) {
		return dashboard
	}
	return await fallbackGetDashboard(staffId)
}

export async function getDeliveryOrdersByStaffId(staffId: string, query: DeliveryOrderQueryType): Promise<Array<DeliveryOrderType>> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_ORDER_LIST, {
		p_staff_id: staffId,
		p_tab: query.tab,
		p_keyword: query.keyword
	} as UTSJSONObject)
	const orders = normalizeRpcOrderList(rpcData)
	if (orders != null) {
		return orders
	}
	return await fallbackGetOrders(staffId, query)
}

export async function getDeliveryOrderDetailById(orderId: string): Promise<DeliveryOrderType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_ORDER_DETAIL, {
		p_order_id: orderId
	} as UTSJSONObject)
	const order = normalizeRpcOrder(rpcData)
	if (order != null) {
		return order
	}
	return await fallbackGetOrderDetail(orderId)
}

export async function acceptDeliveryOrderById(orderId: string): Promise<DeliveryOrderType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_ACCEPT_ORDER, {
		p_order_id: orderId
	} as UTSJSONObject)
	const order = normalizeRpcOrder(rpcData)
	if (order != null) {
		return order
	}
	return await fallbackAcceptOrder(orderId)
}

export async function rejectDeliveryOrderById(orderId: string, reason: string): Promise<DeliveryOrderType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_REJECT_ORDER, {
		p_order_id: orderId,
		p_reason: reason
	} as UTSJSONObject)
	const order = normalizeRpcOrder(rpcData)
	if (order != null) {
		return order
	}
	return await fallbackRejectOrder(orderId, reason)
}

export async function startDepartById(orderId: string, location: DeliveryLocationType): Promise<DeliveryOrderType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_START_DEPART, {
		p_order_id: orderId,
		p_location: location
	} as UTSJSONObject)
	const order = normalizeRpcOrder(rpcData)
	if (order != null) {
		return order
	}
	return await fallbackStartDepart(orderId, location)
}

export async function arriveOrderById(orderId: string, location: DeliveryLocationType): Promise<DeliveryOrderType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_ARRIVE_ORDER, {
		p_order_id: orderId,
		p_location: location
	} as UTSJSONObject)
	const order = normalizeRpcOrder(rpcData)
	if (order != null) {
		return order
	}
	return await fallbackArriveOrder(orderId, location)
}

export async function checkinOrderById(orderId: string, payload: DeliveryCheckinPayloadType): Promise<DeliveryOrderType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_CHECKIN_ORDER, {
		p_order_id: orderId,
		p_payload: payload
	} as UTSJSONObject)
	const order = normalizeRpcOrder(rpcData)
	if (order != null) {
		return order
	}
	return await fallbackCheckinOrder(orderId, payload)
}

export async function startServiceById(orderId: string): Promise<DeliveryOrderType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_START_SERVICE, {
		p_order_id: orderId
	} as UTSJSONObject)
	const order = normalizeRpcOrder(rpcData)
	if (order != null) {
		return order
	}
	return await fallbackStartService(orderId)
}

export async function saveServiceProgressById(orderId: string, payload: DeliveryProgressPayloadType): Promise<DeliveryOrderType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_SAVE_PROGRESS, {
		p_order_id: orderId,
		p_payload: payload
	} as UTSJSONObject)
	const order = normalizeRpcOrder(rpcData)
	if (order != null) {
		return order
	}
	return await fallbackSaveProgress(orderId, payload)
}

export async function uploadEvidenceById(orderId: string, phase: string, files: Array<string>): Promise<Array<DeliveryEvidenceRecordType>> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_UPLOAD_EVIDENCE, {
		p_order_id: orderId,
		p_phase: phase,
		p_files: files
	} as UTSJSONObject)
	const evidenceList = normalizeRpcEvidenceList(rpcData)
	if (evidenceList != null) {
		return evidenceList
	}
	return await fallbackUploadEvidence(orderId, phase, files)
}

export async function retryEvidenceById(orderId: string, evidenceId: string): Promise<DeliveryEvidenceRecordType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_RETRY_EVIDENCE, {
		p_order_id: orderId,
		p_evidence_id: evidenceId
	} as UTSJSONObject)
	if (rpcData != null) {
		return rpcData as DeliveryEvidenceRecordType
	}
	return await fallbackRetryEvidence(orderId, evidenceId)
}

export async function submitExceptionById(orderId: string, payload: DeliveryExceptionPayloadType): Promise<DeliveryOrderType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_SUBMIT_EXCEPTION, {
		p_order_id: orderId,
		p_payload: payload
	} as UTSJSONObject)
	const order = normalizeRpcOrder(rpcData)
	if (order != null) {
		return order
	}
	return await fallbackSubmitException(orderId, payload)
}

export async function finishServiceById(orderId: string, payload: DeliveryFinishPayloadType): Promise<DeliveryOrderType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_FINISH_SERVICE, {
		p_order_id: orderId,
		p_payload: payload
	} as UTSJSONObject)
	const order = normalizeRpcOrder(rpcData)
	if (order != null) {
		return order
	}
	return await fallbackFinishService(orderId, payload)
}

export async function getDeliveryRecordsByStaffId(staffId: string): Promise<Array<DeliveryRecordType>> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_RECORD_LIST, {
		p_staff_id: staffId
	} as UTSJSONObject)
	const records = normalizeRpcRecords(rpcData)
	if (records != null) {
		return records
	}
	return await fallbackGetRecords(staffId)
}

export async function getDeliveryMessagesList(): Promise<Array<DeliveryMessageType>> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_MESSAGE_LIST, {} as UTSJSONObject)
	const messages = normalizeRpcMessages(rpcData)
	if (messages != null && messages.length > 0) {
		return messages
	}
	return await fallbackGetMessages()
}

export async function updateDeliveryOnlineStatusByStaffId(staffId: string, status: string): Promise<DeliveryInfoType | null> {
	const rpcData = await callDeliveryRpc(DELIVERY_RPC_SET_ONLINE_STATUS, {
		p_staff_id: staffId,
		p_status: status
	} as UTSJSONObject)
	const deliveryInfo = normalizeRpcDeliveryInfo(rpcData)
	if (deliveryInfo != null) {
		return deliveryInfo
	}
	return await fallbackUpdateOnlineStatus(staffId, status)
}