import { Module, ModuleOptions, PisellCore } from '../../types';
import { BookingTicketCartView, BookingTicketProductCatalogView, BookingTicketState, IGetCustomerListParams, ICustomer, ILoadProductsParams, ILoadProductDetailParams, IScanResult } from './types';
import type { ProductData } from '../../modules';
import { type BookingContextConfig, type BookingContextDateInput, type BookingContextResource, type BookingContextResourceMap, type BookingContextState, type InitBookingContextParams, type LoadBookingConfigParams, type LoadBookingResourcesParams, type ResourceError, type BookingCalcContext } from '../../modules/BookingContext';
import type { OrderCustomerView } from '../../modules/Order/types';
import { BaseSalesImpl } from '../BaseSales';
import type { BaseSalesScanCodeResult } from '../BaseSales/types';
import type { ISalesDetail } from '../BaseSales/utils/parseSalesResponse';
import type { LoadSalesDetailParams } from '../../modules/Order/types';
import type { GlobalScanHandleResult, GlobalScanHostBridge } from './types';
import { AddProductDecideContext, AddProductRequiresDetailPayload } from './utils/addProductDecision';
import { type BuildCacheItemFromOrderLineInput } from '../../modules/BookingContext/utils/buildCacheItemFromOrderLine';
import { type BuildNormalProductCacheItemFromOrderLineInput } from '../../modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine';
import type { AddProductBookingInput, OrderProduct, OrderProductIdentity, UpdateOrderProductParams } from '../../modules/Order/types';
import { type TransitionChildBookingParams } from './utils/bookingStatus';
export type { BookingTransitionAction, TransitionChildBookingParams, } from './utils/bookingStatus';
export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
    protected defaultName: string;
    protected defaultVersion: string;
    /**
     * 子类覆盖 store 类型为 BookingTicket 子模块清单（在父类基础上追加 customer）。
     * 父类按 `getRegisteredModuleNames` 注入成员到该 store。
     */
    protected store: BookingTicketState;
    private platform;
    private scan;
    private productCatalog;
    private orderCustomerDiscountRefreshInFlight;
    private orderCustomerDiscountRefreshCustomerId;
    private loadOpenDataConfigInFlight;
    /**
     * 在 BaseSales 默认模块清单（products/order/salesSummary/schedule）基础上追加 customer + bookingContext。
     * bookingContext 是 SalesSdk 加车下沉所需的「预约 UI 上下文」（bookingConfig / resourcesOrigin / date）。
     */
    protected getRegisteredModuleNames(): readonly string[];
    protected getSubmitOrderSalesChannel(): string;
    /**
     * 业务侧子模块工厂：BookingTicket 自带的 createBookingTicketModule 优先匹配；
     * 未识别的模块名（如 BookingByStep 公共类型）回退到父类工厂。
     */
    protected createSubModule(moduleName: string): Module | null;
    initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
    private getBookingTicketBusinessCode;
    private getIdGeneratorPlugin;
    private loadOpenDataConfig;
    private getShortNumberOrDeviceId;
    private configureIdGeneratorFromOpenData;
    private normalizePositiveInteger;
    private normalizeIdPrefix;
    /**
     * 加载销售详情，并在父类基础上把 customer 信息装配到 CustomerModule。
     *
     * 业务上 ticketBooking 进入「编辑/查看」时需要 active customer 状态，因此从
     * sales.customer / sales.header / tempOrder 顶层字段中拼装 ICustomer 后调 setSelectedCustomer，
     * 让现有 setActiveCustomer / getActiveCustomer 调用方零成本拿到详情态客户。
     */
    loadSalesDetail(orderIdOrParams: number | string | LoadSalesDetailParams): Promise<ISalesDetail>;
    scanPromotionCode(code: string, customerId?: number): Promise<BaseSalesScanCodeResult>;
    private hydrateOrderCustomerFromScanDiscounts;
    private getDiscountCustomerId;
    private resolveCustomerByDiscountCustomerId;
    private findCustomerById;
    private normalizeCustomer;
    private getRawCustomerId;
    private hasUsableCustomerDetails;
    /**
     * 更新当前预约的 appointment_status。
     *
     * 数据源：从 OrderModule.tempOrder 内部读取，调用方无需传 orderId / scheduleId。
     * schedule id 解析优先级：
     *   1. `tempOrder.metadata.appointment_booking_parent_schedule_id`
     *   2. `tempOrder.bookings` 中 `parent_id === 0` 的 `schedule_event_id`
     *
     * 流程：先乐观更新本地 bookings 的 appointment_status，再调 PUT 接口，
     * 接口成功后强制刷新销售详情；任一步失败都回滚本地状态并抛错。
     *
     * @param status 目标状态（如 'confirmed'）
     * @returns 接口返回的 data
     */
    setBookingStatus(status: string): Promise<any>;
    /**
     * 子预约状态机转移（POST /schedule/booking-transition/{schedule_event_id}）。
     *
     * 与 `setBookingStatus`（父预约 PUT appointment-status）不同，本方法按子预约
     * `schedule_event_id` 调用状态转移接口，body 为 `{ action }`。
     *
     * 流程：能解析出目标状态时先乐观更新对应子预约的 `appointment_status`，
     * 再调 POST；成功后强制刷新销售详情；失败则回滚该子预约本地状态并抛错。
     * `reschedule` 暂未启用状态矩阵，跳过乐观更新仅调接口。
     *
     * @param params.schedule_event_id 子预约 schedule_event_id
     * @param params.action 转移动作：confirm | reject | arrive | start | complete | cancel | no_show | reschedule
     * @returns 接口返回的 data
     *
     * @example
     * await bookingTicket.transitionChildBooking({
     *   schedule_event_id: 301,
     *   action: 'confirm',
     * });
     */
    transitionChildBooking(params: TransitionChildBookingParams): Promise<any>;
    /**
     * 基于当前 tempOrder.order_id 强制从远端重新拉取销售详情。
     *
     * 适用场景：在 BookingTicket 内执行了「修改服务端订单状态」的动作（如改预约状态、
     * 改下单客户、改商品行等）后，统一刷新本地销售详情，保证 UI 与服务端一致。
     *
     * 约束：调用前必须已有 tempOrder 且 order_id 存在，否则视为非法调用并抛错。
     *
     * @returns loadSalesDetail 的返回值
     */
    refreshSalesDetail(): Promise<ISalesDetail>;
    /**
     * 获取商品列表
     * @param params 包含 schedule_date 的参数
     * @returns 商品列表
     */
    loadProducts(params?: ILoadProductsParams, options?: {
        callback?: (result: any) => void;
        subscriberId?: string;
    }): Promise<any>;
    /**
     * 只读查询单商品详情：走 ProductList 报价查询，但不写 productCatalog、
     * 不 emit onProductsLoaded、不修改 BookingDate。
     *
     * 供「列表已 loadProducts、仅需补 product_resource / capacity」等场景使用，
     * 避免 loadProductDetail 覆盖左侧商品列表。
     *
     * @example
     * const detail = await bookingTicket.queryProductDetail({
     *   product_id: 2,
     *   schedule_date: '2030-01-15',
     *   schedule_datetime: '2030-01-15 10:00:00',
     * });
     */
    queryProductDetail(params: ILoadProductDetailParams, options?: {
        callback?: (result: any) => void;
        subscriberId?: string;
    }): Promise<ProductData | undefined>;
    /**
     * 按预约时间加载单个商品详情。
     * 价格仍由 server products 的报价单桥接统一计算，避免 solution 实例重复请求报价单。
     */
    loadProductDetail(params: ILoadProductDetailParams, options?: {
        callback?: (result: any) => void;
        subscriberId?: string;
    }): Promise<ProductData | undefined>;
    /**
     * 取消商品查询订阅
     * @param subscriberId 订阅时传入的 subscriberId
     */
    unsubscribeProductQuery(subscriberId?: string): void;
    /**
     * 初始化外设扫码结果监听
     */
    initPeripheralsListener(): void;
    /**
     * 获取商品列表（不加载到模块中）
     * @returns 商品列表
     */
    getProducts(): Promise<ProductData[]>;
    /**
     * 获取当前已加载的商品池 UI 视图。
     *
     * ProductList.getProducts 是异步 API；BookingTicket 维护最近一次 loadProducts 结果，
     * 供 UI 同步 getter 使用。未加载时返回空列表。
     */
    getProductCatalog(): BookingTicketProductCatalogView;
    /**
     * 获取购物车 UI 视图。
     *
     * tempOrder 仍是 checkout 协议对象；商品行直接透传 products，bookings 附带关联商品。
     */
    getCart(): BookingTicketCartView;
    /**
     * 获取当前下单客户（与 OrderModule.tempOrder snapshot 一致）。
     */
    getCustomer(): ICustomer | null;
    /**
     * 通过 ids 获取商品列表（不加载到模块中）
     * @returns 商品列表
     */
    getProductByIds(ids: number[]): Promise<ProductData[] | undefined>;
    /**
     * 获取日程时间段点
     * @param params 参数
     * @returns 日程时间段点
     */
    getScheduleTimePoints(params: {
        menu_list_ids: number[];
    }): Promise<any>;
    /**
     * 获取客户列表
     * @param params 查询参数
     * @returns 客户列表响应
     */
    getCustomerList(params?: IGetCustomerListParams): Promise<import("../../modules").ICustomerListResponse>;
    /**
     * 设置活跃客户
     * @param customer 客户信息
     */
    setActiveCustomer(customer: ICustomer): void;
    /**
     * 获取当前活跃客户
     * @returns 当前活跃客户
     */
    getActiveCustomer(): ICustomer | null;
    /**
     * 根据ID设置选中的客户
     * @param customerId 客户ID
     */
    setSelectedCustomerById(customerId: string | number): void;
    /**
     * 获取所有客户
     * @returns 客户列表
     */
    getCustomers(): ICustomer[];
    /**
     * 根据ID获取客户
     * @param customerId 客户ID
     * @returns 客户信息
     */
    getCustomerById(customerId: string | number): ICustomer | null;
    /**
     * 清空客户列表
     */
    clearCustomers(): void;
    /**
     * 添加客户到列表第一位
     * @param customer 要添加的客户信息
     */
    addCustomerToFirst(customer: ICustomer): void;
    /**
     * 设置当前下单客户。
     *
     * @param customer 完整客户对象；null 表示清空
     *
     * 内部将 customer 格式化为 tempOrder 协议字段后写入 OrderModule，
     * 并以 customer 作为 snapshot 保存富字段。
     *
     * 同时透传 OrderModule 内部 emit 的 `order:onOrderCustomerChange` 之外，
     * 在 BookingTicket 命名空间也 emit 一次，方便上层统一从 Solution 订阅。
     */
    setOrderCustomer(customer: ICustomer | null): void;
    /**
     * 读取 tempOrder 上的下单客户协议字段；customer_id 缺失时返回 null。
     */
    getOrderCustomer(): OrderCustomerView | null;
    /**
     * 读取 tempOrder._extend.customerSnapshot 中的完整客户对象。
     */
    getOrderCustomerSnapshot(): ICustomer | null;
    /**
     * 清空下单客户（协议字段 + snapshot）。
     */
    clearOrderCustomer(): void;
    /**
     * 重置 tempOrder，并同步清空下单客户运行态。
     *
     * OrderModule.restoreOrder 会重建空单（customer_id 已为 null），但不会：
     *  - emit BookingTicket `onOrderCustomerChange`
     *  - 重置 CustomerModule.selectedCustomer（老路 getActiveCustomer）
     *
     * 因此在 super.restoreOrder 之后显式清客户，保证 SalesSdk / ticketBooking 订阅方与 tempOrder 一致。
     */
    restoreOrder(): Promise<import("../../modules/Order/types").OrderTempOrder>;
    /** 内部：基于 OrderModule 当前状态构造一份 OrderCustomerChangePayload。 */
    private buildOrderCustomerPayload;
    private refreshDiscountConfigAfterOrderCustomerChange;
    /**
     * 获取客户分页信息
     * @returns 分页信息
     */
    getCustomerPaginationInfo(): import("../../modules").IPaginationInfo;
    /**
     * 获取客户列表总数
     * @returns 总数
     */
    getCustomerTotal(): number;
    /**
     * 设置客户分页信息
     * @param page 页码
     * @param pageSize 每页数量
     */
    setCustomerPaginationInfo(page: number, pageSize: number): void;
    /**
     * 便捷方法：切换客户分页并自动获取数据
     * @param page 页码
     * @param pageSize 每页数量（可选）
     * @returns 客户列表响应
     */
    changeCustomerPage(page: number, pageSize?: number): Promise<import("../../modules").ICustomerListResponse>;
    /**
     * 滚动加载更多客户数据 - 数据会追加到现有列表中
     * @returns 客户列表响应
     */
    loadMoreCustomers(): Promise<import("../../modules").ICustomerListResponse>;
    /**
     * 重置并重新开始滚动加载客户数据
     * @param params 查询参数
     * @returns 客户列表响应
     */
    resetAndLoadCustomers(params?: IGetCustomerListParams): Promise<import("../../modules").ICustomerListResponse>;
    /**
     * 检查是否还有更多客户数据可以加载
     * @returns 是否还有更多数据
     */
    hasMoreCustomers(): boolean;
    /**
     * 获取当前的客户搜索条件
     * @returns 当前搜索条件
     */
    getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
    /**
     * 获取客户列表状态（包含滚动加载相关状态）
     * @returns 客户状态
     */
    getCustomerState(): import("../../modules").CustomerState;
    /**
     * 全局扫描监听
     * @param callback 回调
     */
    scanGlobalListener(callback: (data: IScanResult) => void): {
        remove: () => void;
    };
    /**
     * 客户扫描监听
     * @param callback 回调
     */
    scanCustomerListener(callback: (data: IScanResult) => void): {
        remove: () => void;
    };
    /**
     * @title 通用扫描监听
     * @description 直接将扫描结果返回给调用方
     * @param callback 回调
     */
    scanUniversalListener(callback: (data: IScanResult) => void, key: string): {
        remove: () => void;
    };
    /**
     * 调用摄像头
     * @param data 用户自定义数据
     */
    activateCamera(data?: {
        [key: string]: any;
    }): void;
    /**
     * 禁用所有扫描监听
     */
    disableAllScanListeners(): void;
    /**
     * 启用所有扫描监听
     */
    enableAllScanListeners(): void;
    /**
     * 清空所有扫描监听对应的任务执行队列
     */
    clearAllScanListenersTaskQueue(): void;
    /**
     * 设置其他参数
     * @param params 参数
     * @param options 选项
     */
    setOtherParams(params: Record<string, any>, { cover }?: {
        cover?: boolean;
    }): Promise<void>;
    /**
     * 获取其他参数
     * @returns 其他参数
     */
    getOtherParams(): Promise<Record<string, any>>;
    /** 拉取 board config 并写入 BookingContext。 */
    loadBookingConfig(params?: LoadBookingConfigParams): Promise<BookingContextConfig | null>;
    /** 拉取资源全集并写入 BookingContext。 */
    loadBookingResources(params?: LoadBookingResourcesParams): Promise<BookingContextResource[]>;
    /** 初始化 BookingContext（date + config + resources）。 */
    initBookingContext(params?: InitBookingContextParams): Promise<BookingContextState>;
    /** 当前 store 是否已具备与入参等价的 config / resources（无需再请求接口）。 */
    isBookingContextReady(params?: InitBookingContextParams): boolean;
    /** 写入 booking config（来源：`/core/board/management/config`）。 */
    setBookingConfig(config: BookingContextConfig | null): void;
    /** 读取当前 booking config。 */
    getBookingConfig(): BookingContextConfig | null;
    /** 写入资源全集（来源：`/form/schedule`），同步派生 resourcesOriginMap。 */
    setResources(resources: BookingContextResource[] | null | undefined): void;
    /** 读取资源全集（浅克隆）。 */
    getResourcesOrigin(): BookingContextResource[];
    /** 读取资源全集 map（id → resource）。 */
    getResourcesOriginMap(): BookingContextResourceMap;
    /** 写入当前选择的日期；支持 dayjs / Date / string。 */
    setBookingDate(date: BookingContextDateInput): void;
    /** 读取当前选择的日期（统一 string）。 */
    getBookingDate(): string | null;
    /** 读取 BookingContext 完整 store（调试 / 测试 / 透传给 SDK 使用）。 */
    getBookingContextState(): BookingContextState;
    /** 清空 BookingContext（切租户 / destroy 场景）。 */
    clearBookingContext(): void;
    /**
     * 构造 BookingContext 计算上下文（供 getProductExtend / getResourceByIds 等读 API 复用）。
     */
    private buildBookingCalcContext;
    /**
     * 取商品当前可选资源列表（透传 OS BookingContext utils#getResourceByIds）。
     * `extraResources` 用于把拖入未绑定的资源也展示出来。
     */
    getResourcesForProduct(product: any, options?: {
        extraResources?: Array<{
            form_id: number | string;
            id: number;
        }>;
    }): any[];
    /**
     * 拼装 cacheItem 的 _extend / _data（资源 / 容量 / timeObj），与 info2 `getProductExtend` 等价。
     */
    getProductExtend(cacheItem: any, extra?: Partial<BookingCalcContext>): any;
    /**
     * 取资源不可用原因列表（结构化 enum + params，i18n 文案由 UI 渲染）。
     */
    getResourceErrors(resource: any, cacheItem: any): ResourceError[];
    /**
     * session 商品 catalog 日期与 TimeBar 不一致时写业务日志。
     *
     * @example
     * this.logSessionCatalogDateMismatch(product, ctx.date);
     */
    private logSessionCatalogDateMismatch;
    /**
     * 加车前：session 商品 catalog 日历日与 bookingDate 不一致时中断加购，交由 SDK reload products。
     */
    private resolveSessionCatalogBeforeAdd;
    /**
     * 拼装 addProductDecision 通用上下文（从 store 自取）。
     */
    private buildAddProductCtx;
    /**
     * 加车两阶段主决策（规格弹窗 / 资源编辑 / 直接加车）。
     * 与 ticketBooking `handleSelectProduct` + `handleBooking4Service` 等价。
     */
    decideAddProduct(item: any, options?: Partial<AddProductDecideContext>): {
        action: "reloadCatalog";
    } | {
        action: "add";
        cacheItem: any;
    } | {
        action: "requiresDetail";
        payload: AddProductRequiresDetailPayload;
    } | {
        action: "requiresBookingEdit";
        cacheItem: any;
        payload: import("./utils/addProductDecision").AddProductRequiresBookingEditPayload;
    };
    /** 规格弹窗 callback 后的第二段决策。 */
    decideAfterDetail(cacheItem: any, options?: Partial<AddProductDecideContext>): import("./utils/addProductDecision").AddProductDecision;
    /**
     * @deprecated 请用 `decideAddProduct`；`autoClose=true` 仅当 action=add。
     */
    decideAutoClose(item: any, options?: Partial<AddProductDecideContext>): {
        autoClose: boolean;
        cacheItem?: any;
    };
    /** 替代 info2 `getIsEject`：商品是否需要弹窗（0/1）。 */
    getIsEject(item: any, type?: 'select' | 'detail'): 0 | 1;
    /** 仅 session 商品（无 variant/option/package）→ true。 */
    getIsOnlySession(item: any): boolean;
    /**
     * 拼装 requiresDetail payload（给 SDK 直接 return 给 UI 用）。
     */
    buildRequiresDetailPayload(item: any, options?: Partial<AddProductDecideContext>): AddProductRequiresDetailPayload;
    /**
     * 把 detail 弹窗回调结果（e, extension_type, detail）转换为 `(product, booking)` 入参。
     * 内部会先拼 cacheItem，再走 cacheItemToBookingInput 严格协议对齐。
     */
    transformDetailToProductAndBooking(input: {
        item: any;
        cacheItem?: any;
        detailResult?: {
            e: any;
            extension_type?: any;
            detail?: any;
        };
        options?: Partial<AddProductDecideContext>;
    }): {
        product: Partial<OrderProduct> & OrderProductIdentity;
        booking?: AddProductBookingInput;
        cacheItem: any;
    };
    /**
     * 从已加车的 order line + booking 反查资源编辑抽屉所需的 cacheItem。
     * 供 SalesSdk「编辑资源」等场景使用；字段语义与 buildCacheItemFromDetail 产出对齐。
     */
    buildCacheItemFromOrderLine(input: BuildCacheItemFromOrderLineInput): Record<string, any>;
    /**
     * 从已加车的普通商品 order line 反查 SkuDetailModal edit 所需的 cacheItem。
     */
    buildNormalProductCacheItemFromOrderLine(input: BuildNormalProductCacheItemFromOrderLineInput): Record<string, any>;
    /** 文档别名：与 OrderModule.updateOrderProduct 一致。 */
    updateProductInOrder(params: UpdateOrderProductParams): Promise<OrderProduct[]>;
    /**
     * 全局扫码 pubsub 入口：解析码值 → 搜索 → 业务分发（客户 / 加车 / 开单）。
     * UI 层在 pubsub 订阅回调里注入 `bridge`（uiHosts / action / cart.confirm*）。
     *
     * @example
     * ```ts
     * await bookingTicket.handleGlobalScanCode(payload.data, {
     *   openProductDetail: uiHosts.openProductDetail,
     *   confirmDetail: cart.confirmDetail,
     *   openOrder: ({ order_id }) => action({ type: 'pisell1.handleOpenCachedBigSale', data: { order_id } }),
     * });
     * ```
     */
    handleGlobalScanCode(code: string, bridge?: GlobalScanHostBridge): Promise<GlobalScanHandleResult>;
    /**
     * 销毁模块：先调用父类（销毁所有 store 内子模块 + emit destroy + super.destroy()），
     * 再清理 BookingTicket 自有资源（scan 监听 + scan 内存缓存）。
     */
    destroy(): Promise<void>;
}
export * from './types';
export { BookingTicketImpl as BookingTicket };
