import supa from '@/components/supadb/aksupainstance.uts'
import { getCurrentUserId } from '@/utils/store.uts'
import { getCurrentUser } from '@/utils/store.uts'
import type { UserAddress } from '@/utils/supabaseService.uts'
import type { HomeServiceCatalogType } from '@/types/home-service.uts'
import type { DeliveryServiceRecordType } from '@/types/delivery.uts'
import {
	getServiceOrderStatusText,
	normalizeServiceOrderStatus,
	type ServiceOrderAddressSnapshotType,
	type ServiceEvidenceFileType,
	type ServiceExecutionRecordType,
	type ServiceOrderStatus,
	type ServiceOrderTimelineItemType,
	type ServiceOrderType,
	type ServiceReviewType
} from '@/types/service-order.uts'

export type CreateServiceOrderParams = {
	service: HomeServiceCatalogType
	address: ServiceOrderAddressSnapshotType
	recipientName: string
	recipientPhone: string
	contactName: string
	contactPhone: string
	appointmentTime: string
	remark: string
}

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

function nowIso(): string {
	return new Date().toISOString()
}

function buildId(prefix: string): string {
	return prefix + '-' + String(Date.now()) + '-' + String(Math.floor(Math.random() * 100000)).padStart(5, '0')
}

function buildHex(length: number): string {
	const chars = '0123456789abcdef'
	let result = ''
	for (let i = 0; i < length; i++) {
		result += chars.charAt(Math.floor(Math.random() * chars.length))
	}
	return result
}

function buildUuidLike(): string {
	const segment1 = buildHex(8)
	const segment2 = buildHex(4)
	const segment3 = '4' + buildHex(3)
	const variants = '89ab'
	const segment4 = variants.charAt(Math.floor(Math.random() * variants.length)) + buildHex(3)
	const segment5 = buildHex(12)
	return segment1 + '-' + segment2 + '-' + segment3 + '-' + segment4 + '-' + segment5
}

function buildOrderNo(): string {
	const date = new Date()
	const y = String(date.getFullYear())
	const m = String(date.getMonth() + 1).padStart(2, '0')
	const d = String(date.getDate()).padStart(2, '0')
	const h = String(date.getHours()).padStart(2, '0')
	const i = String(date.getMinutes()).padStart(2, '0')
	const s = String(date.getSeconds()).padStart(2, '0')
	return 'HS' + y + m + d + h + i + s + String(Math.floor(Math.random() * 900) + 100)
}

function isUuidLike(value: string): boolean {
	return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/.test(value)
}

function normalizeUuidOrNull(value: string): string | null {
	if (value == '') {
		return null
	}
	return isUuidLike(value) ? value : null
}

function normalizeAppointmentTime(value: string): string | null {
	const text = value.trim()
	if (text == '') {
		return null
	}
	if (/^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}(\s*-\s*\d{2}:\d{2})?$/.test(text)) {
		return text
	}
	if (/^\d{4}-\d{2}-\d{2}(\s+(上午|下午|晚上))$/.test(text)) {
		return text
	}
	if (/^\d{4}-\d{2}-\d{2}T/.test(text)) {
		const parsed = Date.parse(text)
		if (!isNaN(parsed)) {
			const date = new Date(parsed)
			const year = String(date.getFullYear())
			const month = String(date.getMonth() + 1).padStart(2, '0')
			const day = String(date.getDate()).padStart(2, '0')
			const hour = String(date.getHours()).padStart(2, '0')
			const minute = String(date.getMinutes()).padStart(2, '0')
			return year + '-' + month + '-' + day + ' ' + hour + ':' + minute
		}
		return text.replace('T', ' ')
	}
	const monthDayMatch = text.match(/(\d{2})\/(\d{2})/)
	if (monthDayMatch != null) {
		const month = monthDayMatch[1] ?? ''
		const day = monthDayMatch[2] ?? ''
		if (month == '' || day == '') {
			return text
		}
		const year = String(new Date().getFullYear())
		const rangeMatch = text.match(/(\d{2}:\d{2})(\s*-\s*\d{2}:\d{2})?/)
		if (rangeMatch != null) {
			const startTime = rangeMatch[1] ?? ''
			const endRange = rangeMatch[2] ?? ''
			if (startTime != '') {
				return year + '-' + month + '-' + day + ' ' + startTime + endRange.replace(/\s+/g, '')
			}
		}
		const tailText = text.substring(text.indexOf(month + '/' + day) + 5).trim()
		return year + '-' + month + '-' + day + (tailText != '' ? ' ' + tailText : '')
	}
	const explicitParsed = Date.parse(text)
	if (!isNaN(explicitParsed) && /^\d{4}\//.test(text)) {
		const date = new Date(explicitParsed)
		const year = String(date.getFullYear())
		const month = String(date.getMonth() + 1).padStart(2, '0')
		const day = String(date.getDate()).padStart(2, '0')
		const hour = String(date.getHours()).padStart(2, '0')
		const minute = String(date.getMinutes()).padStart(2, '0')
		return year + '-' + month + '-' + day + ' ' + hour + ':' + minute
	}
	const year = String(new Date().getFullYear())
	return /^\d{2}-\d{2}\s+\d{2}:\d{2}/.test(text) ? year + '-' + text : text
}

function safeParseObject(value: string): UTSJSONObject {
	if (value == '') {
		return JSON.parse('{}') as UTSJSONObject
	}
	return JSON.parse(value) as UTSJSONObject
}

function safeParseArray(value: string): Array<string> {
	if (value == '') {
		return [] as Array<string>
	}
	const parsed = JSON.parse(value) as any
	if (Array.isArray(parsed)) {
		return parsed as Array<string>
	}
	return [] as Array<string>
}

function safeJsonField(source: any, key: string): string {
	const plain = JSON.parse(JSON.stringify(source)) as any
	const value = plain[key]
	if (value == null) {
		return ''
	}
	return JSON.stringify(value)
}

function safeFirstJsonField(source: any, keys: Array<string>): string {
	const plain = JSON.parse(JSON.stringify(source)) as any
	for (let i = 0; i < keys.length; i++) {
		const value = plain[keys[i]]
		if (value != null) {
			return JSON.stringify(value)
		}
	}
	return ''
}

function plainObject(source: any): any {
	return JSON.parse(JSON.stringify(source)) as any
}

function readString(source: any, key: string): string {
	const value = plainObject(source)[key]
	if (value == null) {
		return ''
	}
	return typeof value == 'string' ? value : String(value)
}

function readNumber(source: any, key: string): number {
	const value = plainObject(source)[key]
	if (typeof value == 'number') {
		return value
	}
	if (typeof value == 'string' && value != '') {
		const parsed = Number(value)
		return isNaN(parsed) ? 0 : parsed
	}
	return 0
}

function hasMissingColumnError(error: any, columnName: string): boolean {
	if (error == null || columnName == '') {
		return false
	}
	const errorText = JSON.stringify(error).toLowerCase()
	return errorText.indexOf('could not find the') >= 0 && errorText.indexOf(columnName.toLowerCase()) >= 0
}

let ecServiceRequestCreateUnavailable = false

function shouldBypassEcServiceRequestCreate(error: any): boolean {
	if (error == null) {
		return false
	}
	return hasMissingColumnError(error, 'address_snapshot')
		|| hasMissingColumnError(error, 'address_snapshot_json')
		|| hasMissingColumnError(error, 'contact_name')
		|| hasMissingColumnError(error, 'contact_phone')
}

function shouldUseCareTaskPath(orderId: string): boolean {
	return isUuidLike(orderId)
}

function isStaffActive(staff: any): boolean {
	const plain = plainObject(staff)
	if (plain['deleted_at'] != null && String(plain['deleted_at']) != '') {
		return false
	}
	if (plain['is_active'] === false) {
		return false
	}
	return readNumber(staff, 'status') == 1
}

function getStaffPriority(staff: any): number {
	let score = 0
	const onlineStatus = readString(staff, 'online_status')
	if (onlineStatus == 'online') {
		score += 30
	} else if (onlineStatus == 'resting' || onlineStatus == '') {
		score += 20
	} else if (onlineStatus == 'busy') {
		score += 10
	}
	if (readString(staff, 'uid') != '') {
		score += 5
	}
	if (readString(staff, 'station_id') != '') {
		score += 1
	}
	return score
}

async function getAutoAssignableStaff(): Promise<any | null> {
	const staffResponse = await supa
		.from('ml_delivery_staff')
		.select('id, uid, station_id, status, deleted_at, is_active, online_status, updated_at, created_at')
		.eq('status', 1)
		.eq('online_status', 'online')
		.execute()
	if (staffResponse.error != null || staffResponse.data == null) {
		return null
	}
	const rawStaffList = staffResponse.data as Array<any>
	let selected: any = null
	let bestScore = -1
	let bestTime = ''
	for (let i = 0; i < rawStaffList.length; i++) {
		const staff = rawStaffList[i]
		if (!isStaffActive(staff)) {
			continue
		}
		if (readString(staff, 'uid') == '') {
			continue
		}
		const score = getStaffPriority(staff)
		const timeMark = readFirstString(staff, ['updated_at', 'created_at'])
		if (selected == null || score > bestScore || (score == bestScore && timeMark > bestTime)) {
			selected = staff
			bestScore = score
			bestTime = timeMark
		}
	}
	return selected
}

function buildEcServiceRequestPayload(params: CreateServiceOrderParams, userId: string, requestId: string, createdAt: string, appointmentTime: string | null, useAddressSnapshot: boolean): any {
	const payload = {
		id: requestId,
		user_id: userId,
		service_catalog_id: params.service.id,
		service_name: params.service.name,
		service_category: params.service.category,
		elder_name: params.recipientName,
		elder_phone: params.recipientPhone,
		contact_name: params.contactName,
		contact_phone: params.contactPhone,
		scheduled_at: appointmentTime,
		remark: params.remark,
		status: 'ORDER_CREATED',
		created_at: createdAt,
		updated_at: createdAt
	} as any
	if (useAddressSnapshot) {
		payload.address_snapshot = params.address as any
	} else {
		payload.address_snapshot_json = params.address as any
	}
	return payload
}

function buildEcServiceRequestPayloadWithoutAddress(params: CreateServiceOrderParams, userId: string, requestId: string, createdAt: string, appointmentTime: string | null): any {
	return {
		id: requestId,
		user_id: userId,
		service_catalog_id: params.service.id,
		service_name: params.service.name,
		service_category: params.service.category,
		elder_name: params.recipientName,
		elder_phone: params.recipientPhone,
		contact_name: params.contactName,
		contact_phone: params.contactPhone,
		scheduled_at: appointmentTime,
		remark: params.remark,
		status: 'ORDER_CREATED',
		created_at: createdAt,
		updated_at: createdAt
	} as any
}

function buildEcCareTaskPayload(params: CreateServiceOrderParams, userId: string, requestId: string, taskId: string, taskNo: string, createdAt: string, appointmentTime: string | null, useAddressSnapshot: boolean): any {
	const payload = {
		id: taskId,
		task_no: taskNo,
		request_id: requestId,
		user_id: userId,
		service_catalog_id: params.service.id,
		service_name: params.service.name,
		service_category: params.service.category,
		service_snapshot_json: params.service as any,
		elder_name: params.recipientName,
		elder_phone: params.recipientPhone,
		contact_name: params.contactName,
		contact_phone: params.contactPhone,
		scheduled_at: appointmentTime,
		remark: params.remark,
		status: 'ORDER_CREATED',
		created_at: createdAt,
		updated_at: createdAt
	} as any
	if (useAddressSnapshot) {
		payload.address_snapshot = params.address as any
	} else {
		payload.address_snapshot_json = params.address as any
	}
	return payload
}

function buildEcCareTaskPayloadWithoutAddress(params: CreateServiceOrderParams, userId: string, requestId: string, taskId: string, taskNo: string, createdAt: string, appointmentTime: string | null): any {
	return {
		id: taskId,
		task_no: taskNo,
		request_id: requestId,
		user_id: userId,
		service_catalog_id: params.service.id,
		service_name: params.service.name,
		service_category: params.service.category,
		service_snapshot_json: params.service as any,
		elder_name: params.recipientName,
		elder_phone: params.recipientPhone,
		contact_name: params.contactName,
		contact_phone: params.contactPhone,
		scheduled_at: appointmentTime,
		remark: params.remark,
		status: 'ORDER_CREATED',
		created_at: createdAt,
		updated_at: createdAt
	} as any
}

function parseTimeline(item: any): ServiceOrderTimelineItemType {
	return {
		id: readString(item, 'id'),
		orderId: readString(item, 'order_id'),
		fromStatus: readString(item, 'from_status'),
		toStatus: normalizeServiceOrderStatus(readString(item, 'to_status')),
		operatorId: readString(item, 'operator_id'),
		operatorRole: readString(item, 'operator_role'),
		remark: readString(item, 'remark'),
		createdAt: readString(item, 'created_at')
	}
	}

function parseReview(item: any): ServiceReviewType {
	return {
		id: readString(item, 'id'),
		orderId: readString(item, 'order_id'),
		userId: readString(item, 'user_id'),
		rating: readNumber(item, 'rating') == 0 ? 5 : readNumber(item, 'rating'),
		tags: safeParseArray(safeJsonField(item, 'tags_json')),
		content: readString(item, 'content'),
		createdAt: readString(item, 'created_at')
	}
	}

function parseExecutionRecord(item: any): ServiceExecutionRecordType {
	return {
		id: readString(item, 'id'),
		orderId: readString(item, 'order_id'),
		assignmentId: readString(item, 'assignment_id'),
		checkinTime: readString(item, 'checkin_time'),
		checkinLatitude: readNumber(item, 'checkin_latitude'),
		checkinLongitude: readNumber(item, 'checkin_longitude'),
		checkinAddress: readString(item, 'checkin_address'),
		serviceStartedAt: readString(item, 'service_started_at'),
		serviceFinishedAt: readString(item, 'service_finished_at'),
		actualDurationMinutes: readNumber(item, 'actual_duration_minutes'),
		serviceItemsJson: safeJsonField(item, 'service_items_json'),
		summary: readString(item, 'summary'),
		remark: readString(item, 'remark'),
		trackPointsJson: safeJsonField(item, 'track_points_json'),
		createdAt: readString(item, 'created_at'),
		updatedAt: readString(item, 'updated_at')
	}
	}

function parseEvidenceFile(item: any): ServiceEvidenceFileType {
	return {
		id: readString(item, 'id'),
		orderId: readString(item, 'order_id'),
		executionRecordId: readString(item, 'execution_record_id'),
		phase: readString(item, 'phase'),
		fileType: readString(item, 'file_type'),
		storagePath: readString(item, 'storage_path'),
		fileUrl: readString(item, 'file_url'),
		latitude: readNumber(item, 'latitude'),
		longitude: readNumber(item, 'longitude'),
		capturedAt: readString(item, 'captured_at'),
		createdAt: readString(item, 'created_at')
	}
	}

function parseServiceOrder(item: any, logs: Array<ServiceOrderTimelineItemType>, review: ServiceReviewType | null): ServiceOrderType {
	const addressSnapshot = safeFirstJsonField(item, ['address_snapshot_json', 'address_snapshot'])
	const serviceSnapshot = safeJsonField(item, 'service_snapshot_json')
	const addressObj = plainObject(safeParseObject(addressSnapshot))
	const serviceObj = plainObject(safeParseObject(serviceSnapshot))
	return {
		id: readString(item, 'id'),
		orderNo: readString(item, 'order_no'),
		userId: readString(item, 'user_id'),
		serviceId: readString(item, 'service_id'),
		serviceName: readString(item, 'service_name'),
		serviceSnapshot: {
			serviceId: readString(serviceObj, 'serviceId') != '' ? readString(serviceObj, 'serviceId') : readString(item, 'service_id'),
			serviceName: readString(serviceObj, 'serviceName') != '' ? readString(serviceObj, 'serviceName') : readString(item, 'service_name'),
			category: readString(serviceObj, 'category'),
			price: readNumber(serviceObj, 'price'),
			durationText: readString(serviceObj, 'durationText'),
			summary: readString(serviceObj, 'summary'),
			tags: safeParseArray(safeJsonField(serviceObj, 'tags')),
			suitableFor: readString(serviceObj, 'suitableFor')
		},
		serviceAddressId: readString(item, 'service_address_id'),
		addressSnapshot: {
			addressId: readString(addressObj, 'addressId'),
			contactName: readString(addressObj, 'contactName'),
			contactPhone: readString(addressObj, 'contactPhone'),
			province: readString(addressObj, 'province'),
			city: readString(addressObj, 'city'),
			district: readString(addressObj, 'district'),
			detailAddress: readString(addressObj, 'detailAddress'),
			fullAddress: readString(addressObj, 'fullAddress'),
			latitude: readNumber(addressObj, 'latitude'),
			longitude: readNumber(addressObj, 'longitude'),
			coordinateType: readString(addressObj, 'coordinateType') == '' ? 'gcj02' : readString(addressObj, 'coordinateType'),
			remark: readString(addressObj, 'remark')
		},
		recipientName: readString(item, 'recipient_name'),
		recipientPhone: readString(item, 'recipient_phone'),
		contactName: readString(item, 'contact_name'),
		contactPhone: readString(item, 'contact_phone'),
		appointmentTime: readString(item, 'appointment_time'),
		remark: readString(item, 'remark'),
		status: normalizeServiceOrderStatus(readString(item, 'status')),
		currentAssignmentId: readString(item, 'current_assignment_id'),
		currentStaffId: readString(item, 'current_staff_id'),
		acceptedAt: readString(item, 'accepted_at'),
		departedAt: readString(item, 'departed_at'),
		arrivedAt: readString(item, 'arrived_at'),
		serviceStartedAt: readString(item, 'service_started_at'),
		completedAt: readString(item, 'completed_at'),
		pendingAcceptanceAt: readString(item, 'pending_acceptance_at'),
		acceptedByUserAt: readString(item, 'accepted_by_user_at'),
		reviewedAt: readString(item, 'reviewed_at'),
		createdAt: readString(item, 'created_at'),
		updatedAt: readString(item, 'updated_at'),
		staffName: '',
		staffPhone: '',
		logs,
		executionRecord: null,
		evidenceFiles: [] as Array<any>,
		review
	}
	}

async function insertLegacyStatusLog(orderId: string, fromStatus: string, toStatus: ServiceOrderStatus, operatorId: string, operatorRole: string, remark: string): Promise<void> {
	await supa.from('hss_service_order_status_logs').insert({
		id: buildId('slog'),
		order_id: orderId,
		from_status: fromStatus,
		to_status: toStatus,
		operator_id: operatorId == '' ? null : operatorId,
		operator_role: operatorRole,
		remark,
		created_at: new Date().toISOString()
	}).execute()
	}

async function insertWorkOrderEvent(taskId: string, fromStatus: string, toStatus: string, actorId: string, actorRole: string, action: string, remark: string): Promise<void> {
	await supa.from('hc_work_order_events').insert({
		id: buildId('hc-event'),
		task_id: taskId,
		from_status: fromStatus == '' ? null : fromStatus,
		to_status: toStatus,
		actor_id: actorId == '' ? null : actorId,
		actor_role: actorRole,
		action,
		remark,
		created_at: nowIso()
	}).execute()
	}

function readFirstString(source: any, keys: Array<string>): string {
	for (let i = 0; i < keys.length; i++) {
		const value = readString(source, keys[i])
		if (value != '') {
			return value
		}
	}
	return ''
	}

function readFirstNumber(source: any, keys: Array<string>): number {
	for (let i = 0; i < keys.length; i++) {
		const value = readNumber(source, keys[i])
		if (value != 0) {
			return value
		}
	}
	return 0
	}

function readJsonObjectField(source: any, keys: Array<string>): any {
	const plain = plainObject(source)
	for (let i = 0; i < keys.length; i++) {
		const value = plain[keys[i]]
		if (value != null) {
			return value
		}
	}
	return null
	}

function mapCareTaskRowToLegacyOrderRow(item: any): any {
	const serviceSnapshotValue = readJsonObjectField(item, ['service_snapshot_json'])
	const addressSnapshotValue = readJsonObjectField(item, ['address_snapshot', 'address_snapshot_json'])
	let derivedStatus = readString(item, 'status')
	if (readFirstString(item, ['accepted_by_family_at']) != '') {
		derivedStatus = 'ACCEPTED'
	} else if (readFirstString(item, ['acceptance_pending_at']) != '') {
		derivedStatus = 'ACCEPTANCE_PENDING'
	} else if (readString(item, 'service_started_at') != '') {
		derivedStatus = 'ORDER_IN_SERVICE'
	} else if (readFirstString(item, ['checked_in_at']) != '') {
		derivedStatus = 'ORDER_CHECKED_IN'
	} else if (readString(item, 'departed_at') != '') {
		derivedStatus = 'departed'
	} else if (readString(item, 'accepted_at') != '') {
		derivedStatus = 'ORDER_ACCEPTED'
	} else if (readFirstString(item, ['assigned_to']) != '') {
		derivedStatus = 'ORDER_ASSIGNED'
	}
	const serviceSnapshot = serviceSnapshotValue != null ? serviceSnapshotValue : {
		serviceId: readFirstString(item, ['service_catalog_id', 'service_id']),
		serviceName: readString(item, 'service_name'),
		category: readFirstString(item, ['service_category', 'category']),
		price: readFirstNumber(item, ['service_price', 'price']),
		durationText: readFirstString(item, ['service_duration_text', 'duration_text']),
		summary: readFirstString(item, ['service_summary', 'summary']),
		tags: [] as Array<string>,
		suitableFor: readFirstString(item, ['suitable_for'])
	}
	return {
		id: readString(item, 'id'),
		order_no: readFirstString(item, ['task_no', 'order_no']),
		user_id: readFirstString(item, ['user_id', 'requester_user_id']),
		service_id: readFirstString(item, ['service_catalog_id', 'service_id']),
		service_name: readString(item, 'service_name'),
		service_snapshot_json: serviceSnapshot,
		service_address_id: readFirstString(item, ['service_address_id', 'address_id']),
		address_snapshot_json: addressSnapshotValue != null ? addressSnapshotValue : JSON.parse('{}'),
		recipient_name: readFirstString(item, ['elder_name', 'recipient_name']),
		recipient_phone: readFirstString(item, ['elder_phone', 'recipient_phone']),
		contact_name: readString(item, 'contact_name'),
		contact_phone: readString(item, 'contact_phone'),
		appointment_time: readFirstString(item, ['scheduled_at', 'appointment_time']),
		remark: readString(item, 'remark'),
		status: derivedStatus,
		current_assignment_id: readFirstString(item, ['assignment_id', 'current_assignment_id']),
		current_staff_id: readFirstString(item, ['assigned_to', 'current_staff_id']),
		accepted_at: readString(item, 'accepted_at'),
		departed_at: readString(item, 'departed_at'),
		arrived_at: readFirstString(item, ['checked_in_at', 'arrived_at']),
		service_started_at: readString(item, 'service_started_at'),
		completed_at: readFirstString(item, ['service_completed_at', 'completed_at']),
		pending_acceptance_at: readFirstString(item, ['acceptance_pending_at', 'pending_acceptance_at']),
		accepted_by_user_at: readFirstString(item, ['accepted_by_family_at', 'accepted_by_user_at']),
		reviewed_at: readString(item, 'reviewed_at'),
		created_at: readString(item, 'created_at'),
		updated_at: readString(item, 'updated_at')
	}
	}

function mapWorkOrderEventToLegacyLog(item: any): any {
	return {
		id: readString(item, 'id'),
		order_id: readFirstString(item, ['task_id', 'order_id']),
		from_status: readString(item, 'from_status'),
		to_status: readFirstString(item, ['to_status', 'status']),
		operator_id: readFirstString(item, ['actor_id', 'operator_id']),
		operator_role: readFirstString(item, ['actor_role', 'operator_role']),
		remark: readString(item, 'remark'),
		created_at: readString(item, 'created_at')
	}
	}

function mapCareReviewRecordToLegacyReview(item: any): any {
	return {
		id: readString(item, 'id'),
		order_id: readFirstString(item, ['task_id', 'order_id']),
		user_id: readFirstString(item, ['created_by', 'user_id']),
		rating: readFirstNumber(item, ['rating']),
		tags_json: readJsonObjectField(item, ['tags_json']) != null ? readJsonObjectField(item, ['tags_json']) : [] as Array<string>,
		content: readFirstString(item, ['content', 'summary', 'remark']),
		created_at: readString(item, 'created_at')
	}
	}

function buildLegacyExecutionRecord(taskId: string, records: Array<any>): ServiceExecutionRecordType | null {
	if (records.length == 0) {
		return null
	}
	let checkinRecord: any = null
	let serviceRecord: any = null
	for (let i = 0; i < records.length; i++) {
		const recordType = readFirstString(records[i], ['record_type', 'care_record_type'])
		if (recordType == 'review') {
			continue
		}
		if (recordType == 'checkin') {
			checkinRecord = records[i]
			continue
		}
		if (serviceRecord == null) {
			serviceRecord = records[i]
		}
	}
	const target = serviceRecord != null ? serviceRecord : (checkinRecord != null ? checkinRecord : records[0])
	return parseExecutionRecord({
		id: readString(target, 'id'),
		order_id: taskId,
		assignment_id: readFirstString(target, ['assignment_id']),
		checkin_time: checkinRecord != null ? readFirstString(checkinRecord, ['checked_in_at', 'checkin_time', 'started_at']) : readFirstString(target, ['checked_in_at', 'checkin_time']),
		checkin_latitude: checkinRecord != null ? readFirstNumber(checkinRecord, ['latitude', 'checkin_latitude']) : readFirstNumber(target, ['latitude', 'checkin_latitude']),
		checkin_longitude: checkinRecord != null ? readFirstNumber(checkinRecord, ['longitude', 'checkin_longitude']) : readFirstNumber(target, ['longitude', 'checkin_longitude']),
		checkin_address: checkinRecord != null ? readFirstString(checkinRecord, ['location_text', 'checkin_address', 'remark']) : readFirstString(target, ['location_text', 'checkin_address']),
		service_started_at: readFirstString(target, ['started_at', 'service_started_at']),
		service_finished_at: readFirstString(target, ['finished_at', 'service_finished_at']),
		actual_duration_minutes: readFirstNumber(target, ['duration_minutes', 'actual_duration_minutes']),
		service_items_json: readJsonObjectField(target, ['service_items_json']) != null ? readJsonObjectField(target, ['service_items_json']) : [] as Array<any>,
		summary: readFirstString(target, ['summary', 'content']),
		remark: readString(target, 'remark'),
		track_points_json: readJsonObjectField(target, ['track_points_json']) != null ? readJsonObjectField(target, ['track_points_json']) : [] as Array<any>,
		created_at: readString(target, 'created_at'),
		updated_at: readString(target, 'updated_at')
	})
	}

async function getCareTaskDetail(taskId: string): Promise<ServiceOrderType | null> {
	if (!isUuidLike(taskId)) {
		return null
	}
	const taskResponse = await supa.from('ec_care_tasks').select('*').eq('id', taskId).limit(1).execute()
	if (taskResponse.error != null || taskResponse.data == null) {
		return null
	}
	const taskRows = taskResponse.data as Array<any>
	if (taskRows.length == 0) {
		return null
	}
	const eventsResponse = await supa.from('hc_work_order_events').select('*').eq('task_id', taskId).order('created_at', { ascending: false }).execute()
	const recordsResponse = await supa.from('ec_care_records').select('*').eq('task_id', taskId).order('created_at', { ascending: false }).execute()
	const evidenceResponse = await supa.from('hc_evidence_files').select('*').eq('task_id', taskId).order('created_at', { ascending: false }).execute()
	const logs = [] as Array<ServiceOrderTimelineItemType>
	if (eventsResponse.data != null) {
		const rawEvents = eventsResponse.data as Array<any>
		for (let i = 0; i < rawEvents.length; i++) {
			logs.push(parseTimeline(mapWorkOrderEventToLegacyLog(rawEvents[i])))
		}
	}
	let review: ServiceReviewType | null = null
	const recordRows = recordsResponse.data != null ? recordsResponse.data as Array<any> : [] as Array<any>
	for (let i = 0; i < recordRows.length; i++) {
		const recordType = readFirstString(recordRows[i], ['record_type', 'care_record_type'])
		if (recordType == 'review') {
			review = parseReview(mapCareReviewRecordToLegacyReview(recordRows[i]))
			break
		}
	}
	const parsed = parseServiceOrder(mapCareTaskRowToLegacyOrderRow(taskRows[0]), logs, review)
	parsed.executionRecord = buildLegacyExecutionRecord(taskId, recordRows)
	if (evidenceResponse.data != null) {
		const rawEvidence = evidenceResponse.data as Array<any>
		const evidenceFiles = [] as Array<ServiceEvidenceFileType>
		for (let i = 0; i < rawEvidence.length; i++) {
			evidenceFiles.push(parseEvidenceFile({
				id: readString(rawEvidence[i], 'id'),
				order_id: taskId,
				execution_record_id: readFirstString(rawEvidence[i], ['care_record_id', 'execution_record_id']),
				phase: readString(rawEvidence[i], 'phase'),
				file_type: readString(rawEvidence[i], 'file_type'),
				storage_path: readString(rawEvidence[i], 'storage_path'),
				file_url: readString(rawEvidence[i], 'file_url'),
				latitude: readFirstNumber(rawEvidence[i], ['latitude']),
				longitude: readFirstNumber(rawEvidence[i], ['longitude']),
				captured_at: readString(rawEvidence[i], 'captured_at'),
				created_at: readString(rawEvidence[i], 'created_at')
			}))
		}
		parsed.evidenceFiles = evidenceFiles
	}
	if (parsed.currentStaffId != '') {
		const staffResponse = await supa.from('ml_delivery_staff').select('nickname, phone').eq('uid', parsed.currentStaffId).limit(1).execute()
		if (staffResponse.data != null) {
			const rawStaffList = staffResponse.data as Array<any>
			if (rawStaffList.length > 0) {
				parsed.staffName = readString(rawStaffList[0], 'nickname')
				parsed.staffPhone = readString(rawStaffList[0], 'phone')
			}
		}
	}
	return parsed
	}

async function tryCreateCareTask(params: CreateServiceOrderParams): Promise<ServiceOrderType | null> {
	if (ecServiceRequestCreateUnavailable) {
		return null
	}
	const userId = getCurrentUserId()
	if (userId == '') {
		return null
	}
	const requestId = buildUuidLike()
	const taskId = buildUuidLike()
	const taskNo = buildOrderNo()
	const createdAt = nowIso()
	const appointmentTime = normalizeAppointmentTime(params.appointmentTime)
	let requestResponse = await supa.from('ec_service_requests').insert(
		buildEcServiceRequestPayload(params, userId, requestId, createdAt, appointmentTime, true)
	).execute()
	if (shouldBypassEcServiceRequestCreate(requestResponse.error)) {
		ecServiceRequestCreateUnavailable = true
		return null
	}
	if (requestResponse.error != null) {
		requestResponse = await supa.from('ec_service_requests').insert(
			buildEcServiceRequestPayload(params, userId, requestId, createdAt, appointmentTime, false)
		).execute()
	}
	if (shouldBypassEcServiceRequestCreate(requestResponse.error)) {
		ecServiceRequestCreateUnavailable = true
		return null
	}
	if (requestResponse.error != null) {
		requestResponse = await supa.from('ec_service_requests').insert(
			buildEcServiceRequestPayloadWithoutAddress(params, userId, requestId, createdAt, appointmentTime)
		).execute()
	}
	if (shouldBypassEcServiceRequestCreate(requestResponse.error)) {
		ecServiceRequestCreateUnavailable = true
		return null
	}
	if (requestResponse.error != null) {
		return null
	}
	let taskResponse = await supa.from('ec_care_tasks').insert(
		buildEcCareTaskPayload(params, userId, requestId, taskId, taskNo, createdAt, appointmentTime, true)
	).execute()
	if (taskResponse.error != null) {
		taskResponse = await supa.from('ec_care_tasks').insert(
			buildEcCareTaskPayload(params, userId, requestId, taskId, taskNo, createdAt, appointmentTime, false)
		).execute()
	}
	if (taskResponse.error != null) {
		taskResponse = await supa.from('ec_care_tasks').insert(
			buildEcCareTaskPayloadWithoutAddress(params, userId, requestId, taskId, taskNo, createdAt, appointmentTime)
		).execute()
	}
	if (taskResponse.error != null) {
		return null
	}
	await insertWorkOrderEvent(taskId, '', 'ORDER_CREATED', userId, 'consumer', 'create_task', '创建服务申请')
	const assignedStaff = await getAutoAssignableStaff()
	if (assignedStaff != null) {
		const assignedUserId = readString(assignedStaff, 'uid')
		if (assignedUserId != '') {
			await supa.from('ec_care_tasks').update({
				status: 'ORDER_ASSIGNED',
				assigned_to: assignedUserId,
				updated_at: createdAt
			}).eq('id', taskId).execute()
			await insertWorkOrderEvent(taskId, 'ORDER_CREATED', 'ORDER_ASSIGNED', userId, 'system', 'assign_task', '系统已自动派单')
		}
	}
	return await getCareTaskDetail(taskId)
	}

async function getLegacyServiceOrderDetail(orderId: string): Promise<ServiceOrderType | null> {
	const orderResponse = await supa.from('hss_service_orders').select('*').eq('id', orderId).limit(1).execute()
	if (orderResponse.error != null || orderResponse.data == null) {
		return null
	}
	const rawOrders = orderResponse.data as any[]
	if (rawOrders.length == 0) {
		return null
	}
	const logsResponse = await supa.from('hss_service_order_status_logs').select('*').eq('order_id', orderId).order('created_at', { ascending: false }).execute()
	const reviewResponse = await supa.from('hss_service_reviews').select('*').eq('order_id', orderId).order('created_at', { ascending: false }).execute()
	const executionResponse = await supa.from('hss_service_execution_records').select('*').eq('order_id', orderId).order('created_at', { ascending: false }).limit(1).execute()
	const evidenceResponse = await supa.from('hss_service_evidence_files').select('*').eq('order_id', orderId).order('created_at', { ascending: false }).execute()
	const logs = [] as Array<ServiceOrderTimelineItemType>
	if (logsResponse.data != null) {
		const rawLogs = logsResponse.data as any[]
		for (let i = 0; i < rawLogs.length; i++) {
			logs.push(parseTimeline(rawLogs[i]))
		}
	}
	let review: ServiceReviewType | null = null
	if (reviewResponse.data != null) {
		const rawReviews = reviewResponse.data as any[]
		if (rawReviews.length > 0) {
			review = parseReview(rawReviews[0])
		}
	}
	const parsed = parseServiceOrder(rawOrders[0], logs, review)
	if (executionResponse.data != null) {
		const rawExecutionList = executionResponse.data as any[]
		if (rawExecutionList.length > 0) {
			parsed.executionRecord = parseExecutionRecord(rawExecutionList[0])
		}
	}
	if (evidenceResponse.data != null) {
		const rawEvidenceList = evidenceResponse.data as any[]
		const evidenceFiles = [] as Array<ServiceEvidenceFileType>
		for (let i = 0; i < rawEvidenceList.length; i++) {
			evidenceFiles.push(parseEvidenceFile(rawEvidenceList[i]))
		}
		parsed.evidenceFiles = evidenceFiles
	}
	if (parsed.currentStaffId != '') {
		const staffResponse = await supa.from('ml_delivery_staff').select('nickname, phone').eq('id', parsed.currentStaffId).limit(1).execute()
		if (staffResponse.data != null) {
			const rawStaffList = staffResponse.data as any[]
			if (rawStaffList.length > 0) {
				const staffObj = plainObject(rawStaffList[0])
				parsed.staffName = readString(staffObj, 'nickname')
				parsed.staffPhone = readString(staffObj, 'phone')
			}
		}
	}
	return parsed
	}

export function buildAddressSnapshot(address: UserAddress, latitude: number, longitude: number): ServiceOrderAddressSnapshotType {
	return {
		addressId: address.id,
		contactName: address.recipient_name,
		contactPhone: address.phone,
		province: address.province,
		city: address.city,
		district: address.district,
		detailAddress: address.detail_address,
		fullAddress: address.province + address.city + address.district + ' ' + address.detail_address,
		latitude,
		longitude,
		coordinateType: 'gcj02',
		remark: address.label ?? ''
	}
	}

export async function createServiceOrder(params: CreateServiceOrderParams): Promise<ServiceOrderType | null> {
	const newTask = await tryCreateCareTask(params)
	if (newTask != null) {
		return newTask
	}
	const userId = getCurrentUserId()
	if (userId == '') {
		return null
	}
	const orderId = buildId('so')
	const orderNo = buildOrderNo()
	const now = new Date().toISOString()
	const appointmentTime = normalizeAppointmentTime(params.appointmentTime)
	const response = await supa.from('hss_service_orders').insert({
		id: orderId,
		order_no: orderNo,
		user_id: userId,
		service_id: params.service.id,
		service_name: params.service.name,
		service_snapshot_json: params.service as any,
		service_address_id: normalizeUuidOrNull(params.address.addressId),
		address_snapshot_json: params.address as any,
		recipient_name: params.recipientName,
		recipient_phone: params.recipientPhone,
		contact_name: params.contactName,
		contact_phone: params.contactPhone,
		appointment_time: appointmentTime,
		remark: params.remark,
		status: 'created',
		created_at: now,
		updated_at: now
	}).execute()
	if (response.error != null) {
		console.error('createServiceOrder failed', response.error)
		return null
	}
	await insertLegacyStatusLog(orderId, '', 'created', userId, 'consumer', '创建服务订单')
	const staffObj = await getAutoAssignableStaff()
	if (staffObj != null) {
		const plainStaff = plainObject(staffObj)
			const assignmentId = buildId('sa')
			await supa.from('hss_service_assignments').insert({
				id: assignmentId,
				order_id: orderId,
				staff_id: readString(plainStaff, 'id'),
				station_id: readString(plainStaff, 'station_id') == '' ? null : readString(plainStaff, 'station_id'),
				status: 'assigned',
				assigned_at: now,
				created_at: now,
				updated_at: now
			}).execute()
			await supa.from('hss_service_orders').update({
				status: 'assigned',
				current_assignment_id: assignmentId,
				current_staff_id: readString(plainStaff, 'id'),
				updated_at: now
			}).eq('id', orderId).execute()
			await insertLegacyStatusLog(orderId, 'created', 'assigned', userId, 'system', '系统已自动派单')
	}
	return await getLegacyServiceOrderDetail(orderId)
	}

export async function listConsumerServiceOrders(): Promise<Array<ServiceOrderType>> {
	const userId = getCurrentUserId()
	if (userId == '') {
		return [] as Array<ServiceOrderType>
	}
	const careTaskResponse = await supa.from('ec_care_tasks').select('*').eq('user_id', userId).order('created_at', { ascending: false }).execute()
	if (careTaskResponse.error == null && careTaskResponse.data != null) {
		const rawTasks = careTaskResponse.data as Array<any>
		const taskResult = [] as Array<ServiceOrderType>
		for (let i = 0; i < rawTasks.length; i++) {
			const parsed = await getCareTaskDetail(readString(rawTasks[i], 'id'))
			if (parsed != null) {
				taskResult.push(parsed)
			}
		}
		return taskResult
	}
	const response = await supa.from('hss_service_orders').select('*').eq('user_id', userId).order('created_at', { ascending: false }).execute()
	if (response.error != null || response.data == null) {
		return [] as Array<ServiceOrderType>
	}
	const list = response.data as any[]
	const result = [] as Array<ServiceOrderType>
	for (let i = 0; i < list.length; i++) {
		const parsed = await getLegacyServiceOrderDetail(JSON.parse(JSON.stringify(list[i]))['id'] as string)
		if (parsed != null) {
			result.push(parsed)
		}
	}
	return result
	}

export async function getServiceOrderDetail(orderId: string): Promise<ServiceOrderType | null> {
	if (shouldUseCareTaskPath(orderId)) {
		const careTask = await getCareTaskDetail(orderId)
		if (careTask != null) {
			return careTask
		}
	}
	return await getLegacyServiceOrderDetail(orderId)
	}

export async function saveServiceRecord(orderId: string, record: DeliveryServiceRecordType): Promise<ServiceOrderType | null> {
	const userId = getCurrentUserId()
	if (userId == '') {
		return null
	}
	const careTask = shouldUseCareTaskPath(orderId) ? await getCareTaskDetail(orderId) : null
	if (careTask != null) {
		const savedAt = nowIso()
		const serviceContent = record.serviceContent.length > 0 ? record.serviceContent : record.serviceItems.map(item => item.name)
		const serviceSummary = record.serviceSummary != '' ? record.serviceSummary : record.processNote
		const healthMetrics = record.healthMetrics as any
		const familyConfirmation = record.familyConfirmation as any
		const insertResponse = await supa.from('ec_care_records').insert({
			id: buildId('care-record'),
			task_id: orderId,
			record_type: 'service_record',
			created_by: userId,
			service_items_json: record.serviceItems as any,
			service_content_json: serviceContent as any,
			service_summary: serviceSummary,
			process_note: record.processNote,
			elder_status: record.elderStatus,
			health_metrics_json: healthMetrics,
			materials_used: record.materialsUsed,
			abnormal_note: record.abnormalNote,
			photos_json: record.photos as any,
			staff_remark: record.staffRemark,
			family_confirmation_json: familyConfirmation,
			created_at: savedAt,
			updated_at: savedAt
		}).execute()
		if (insertResponse.error != null) {
			return null
		}
		const updateResponse = await supa.from('ec_care_tasks').update({
			updated_at: savedAt
		}).eq('id', orderId).execute()
		if (updateResponse.error != null) {
			return null
		}
		await insertWorkOrderEvent(orderId, careTask.status, careTask.status, userId, 'staff', 'save_service_record', serviceSummary == '' ? '服务记录已保存' : serviceSummary)
		return await getCareTaskDetail(orderId)
	}
	const current = await getLegacyServiceOrderDetail(orderId)
	if (current == null) {
		return null
	}
	const savedAt = nowIso()
	const serviceSummary = record.serviceSummary != '' ? record.serviceSummary : record.processNote
	const saveResponse = await supa.from('hss_service_execution_records').insert({
		id: buildId('ser'),
		order_id: orderId,
		checkin_time: current.executionRecord != null ? current.executionRecord.checkin_time : savedAt,
		checkin_latitude: current.executionRecord != null ? current.executionRecord.checkin_latitude : 0,
		checkin_longitude: current.executionRecord != null ? current.executionRecord.checkin_longitude : 0,
		checkin_address: current.executionRecord != null ? current.executionRecord.checkin_address : '',
		service_content_json: record.serviceContent.length > 0 ? record.serviceContent as any : record.serviceItems.map(item => item.name) as any,
		service_summary: serviceSummary,
		completion_images_json: record.photos as any,
		signature_image: '',
		signature_name: record.familyConfirmation.familyMember,
		created_at: savedAt,
		updated_at: savedAt
	}).execute()
	if (saveResponse.error != null) {
		return null
	}
	await supa.from('hss_service_orders').update({
		updated_at: savedAt
	}).eq('id', orderId).execute()
	return await getLegacyServiceOrderDetail(orderId)
}

export async function confirmServiceOrder(orderId: string, rating: number, content: string, tags: Array<string>): Promise<ServiceOrderType | null> {
	const userId = getCurrentUserId()
	if (userId == '') {
		return null
	}
	const careTask = shouldUseCareTaskPath(orderId) ? await getCareTaskDetail(orderId) : null
	if (careTask != null) {
		const acceptedAt = nowIso()
		const updateResponse = await supa.from('ec_care_tasks').update({
			status: 'ACCEPTED',
			accepted_by_family_at: acceptedAt,
			updated_at: acceptedAt
		}).eq('id', orderId).execute()
		if (updateResponse.error == null) {
			await insertWorkOrderEvent(orderId, 'ACCEPTANCE_PENDING', 'ACCEPTED', userId, 'consumer', 'accept_task', '用户确认验收')
			if (rating > 0 || content != '' || tags.length > 0) {
				await supa.from('ec_care_records').insert({
					id: buildId('care-review'),
					task_id: orderId,
					record_type: 'review',
					created_by: userId,
					rating,
					tags_json: tags as any,
					content,
					created_at: acceptedAt,
					updated_at: acceptedAt
				}).execute()
				await insertWorkOrderEvent(orderId, 'ACCEPTED', 'ACCEPTED', userId, 'consumer', 'submit_review', '用户提交评价')
			}
			return await getCareTaskDetail(orderId)
		}
	}
	const current = await getServiceOrderDetail(orderId)
	if (current == null) {
		return null
	}
	const acceptedAt = new Date().toISOString()
	const updateResponse = await supa.from('hss_service_orders').update({
		status: 'accepted_by_user',
		accepted_by_user_at: acceptedAt,
		updated_at: acceptedAt
	}).eq('id', orderId).execute()
	if (updateResponse.error != null) {
		return null
	}
	await insertLegacyStatusLog(orderId, current.status, 'accepted_by_user', userId, 'consumer', '用户确认验收')
	await supa.from('hss_service_reviews').insert({
		id: buildId('srv'),
		order_id: orderId,
		user_id: userId,
		rating,
		tags_json: tags as any,
		content,
		created_at: acceptedAt
	}).execute()
	await supa.from('hss_service_orders').update({
		status: 'reviewed',
		reviewed_at: acceptedAt,
		updated_at: acceptedAt
	}).eq('id', orderId).execute()
	await insertLegacyStatusLog(orderId, 'accepted_by_user', 'reviewed', userId, 'consumer', '用户提交评价')
	return await getLegacyServiceOrderDetail(orderId)
	}

export async function rejectServiceOrderAcceptance(orderId: string, content: string): Promise<ServiceOrderType | null> {
	const userId = getCurrentUserId()
	if (userId == '') {
		return null
	}
	const careTask = shouldUseCareTaskPath(orderId) ? await getCareTaskDetail(orderId) : null
	if (careTask != null) {
		const rejectedAt = nowIso()
		const updateResponse = await supa.from('ec_care_tasks').update({
			status: 'ACCEPTANCE_REJECTED',
			updated_at: rejectedAt
		}).eq('id', orderId).execute()
		if (updateResponse.error == null) {
			await supa.from('hc_work_order_exceptions').insert({
				id: buildId('hc-ex'),
				task_id: orderId,
				exception_type: 'acceptance_rejected',
				description: content == '' ? '用户退回整改' : content,
				occurred_at: rejectedAt,
				location_text: '',
				images_json: [] as Array<string>,
				need_platform_intervention: false,
				request_cancel_order: false,
				request_reschedule: false,
				created_by: userId,
				created_at: rejectedAt,
				updated_at: rejectedAt
			}).execute()
			await insertWorkOrderEvent(orderId, 'ACCEPTANCE_PENDING', 'ACCEPTANCE_REJECTED', userId, 'consumer', 'reject_acceptance', content == '' ? '用户退回整改' : content)
			return await getCareTaskDetail(orderId)
		}
	}
	const current = await getServiceOrderDetail(orderId)
	if (current == null) {
		return null
	}
	const updateResponse = await supa.from('hss_service_orders').update({
		status: 'exception',
		updated_at: nowIso()
	}).eq('id', orderId).execute()
	if (updateResponse.error != null) {
		return null
	}
	await insertLegacyStatusLog(orderId, current.status, 'exception', userId, 'consumer', content == '' ? '用户退回整改' : content)
	return await getLegacyServiceOrderDetail(orderId)
	}

export async function getCurrentConsumerUser() {
	return await getCurrentUser()
	}