import type { AxelPlaceNetworkEvent } from "@/workers/rpa/axel-selection-bridge"; import type { AddressCommitState, AddressSelectDiagnostics, AddressSelectStatus, } from "@/workers/rpa/address-adapter/types"; export type PlaceNetworkDiagnostic = { placeId: string; status: number; url: string; at: number; }; export type AddressNetworkDiagnostics = { expectedPlaceId: string; observedPlaceIds: string[]; placeNetworkEvents: PlaceNetworkDiagnostic[]; placeRequestObserved: boolean; placeRequestHttpOk: boolean; pickupLostAfterDelivery: boolean; }; export function buildNetworkDiagnostics( bridge: { getObservedPlaceCommitIds: () => string[]; getPlaceNetworkLog: () => readonly AxelPlaceNetworkEvent[]; hasPlaceCommit: (placeId: string) => boolean; hasSuccessfulPlaceNetworkRequest: (placeId: string) => boolean; }, expectedPlaceId: string, pickupPlaceId?: string, ): AddressNetworkDiagnostics { return { expectedPlaceId, observedPlaceIds: bridge.getObservedPlaceCommitIds(), placeNetworkEvents: bridge.getPlaceNetworkLog().map((event) => ({ placeId: event.placeId, status: event.status, url: event.url, at: event.at, })), placeRequestObserved: bridge.hasPlaceCommit(expectedPlaceId), placeRequestHttpOk: bridge.hasSuccessfulPlaceNetworkRequest(expectedPlaceId), pickupLostAfterDelivery: false, }; } export function createEmptyDiagnostics( address: string, commitState: AddressCommitState = "EMPTY", ): AddressSelectDiagnostics { return { address, placeId: "", method: "", events: [], placeRequestObserved: false, status: "selection_failed", commitState, }; } export function formatDiagnosticsFailure(diag: AddressSelectDiagnostics): string { const base = `address=${diag.address.slice(0, 64)} placeId=${diag.placeId || "—"} method=${diag.method || "—"} commitState=${diag.commitState}`; switch (diag.status) { case "no_place_request": return `${base};失败于 place API 前:widget 未发起 GET place 请求(selection event 未触发)`; case "place_http_error": return `${base};失败于 place API:HTTP 非 200`; case "place_id_mismatch": return `${base};失败于 place API:placeId 与预期不匹配`; case "timeout": return `${base};失败于 place API:等待 commit 超时`; case "selection_failed": return `${base};失败于 selection event:候选/绑定/点选未完成`; default: return `${base};地址 commit 未完成`; } } export function logAddressSelectDiagnostics( side: "pickup" | "delivery", diag: AddressSelectDiagnostics, ): void { console.log( `[rpa] address-select:${side} ${JSON.stringify({ address: diag.address, placeId: diag.placeId, method: diag.method, events: diag.events, placeRequestObserved: diag.placeRequestObserved, status: diag.status, commitState: diag.commitState, })}`, ); } export function resolvePlaceFailureStatus( placeRequestObserved: boolean, placeIdMismatch: boolean, httpError: boolean, timedOut: boolean, ): AddressSelectStatus { if (!placeRequestObserved) { return "no_place_request"; } if (placeIdMismatch) { return "place_id_mismatch"; } if (httpError) { return "place_http_error"; } if (timedOut) { return "timeout"; } return "selection_failed"; }