/**
 * Sales SDK 公开类型契约。
 *
 * 该文件不依赖 `@pisell/pisellos` 类型（运行时通过 `appHelper.utils.pisellos` 注入），
 * 因此对底层 OS 类型采用结构性 alias：仅描述 SDK 直接消费/暴露的字段，
 * 其它字段以 `Record<string, any>` 透传。所有 alias 命名严格沿用 OS 协议（`parseSalesResponse` /
 * `ScanOrder` types），避免重新发明等价关系（遵循 .cursor/rules/data-field-semantics.mdc）。
 *
 * SDK 自有的 Provider props / Context value / 视图类型均带 `SalesSdk` 前缀，
 * 以避免与 `components/Sales` 既有 UI 模块同名混淆。
 */
import type React from 'react';
/** OS 商品行 SKU（v2 规格权威源：product_sku.option） */
export interface ScanOrderProductSku {
    option?: any[];
    [key: string]: any;
}
/** 商品行 identity（OS BaseSalesOrderProductIdentity / ScanOrderOrderProductIdentity 子集） */
export interface ScanOrderOrderProductIdentity {
    product_id: number | null;
    product_variant_id: number;
    /** @deprecated 行级唯一值统一使用 metadata.unique_identification_number */
    identity_key?: string;
    unique_identification_number?: string;
    product_sku?: ScanOrderProductSku;
    /** @deprecated 读规格请用 product_sku.option；仅 legacy 缓存/identity 兼容 */
    product_option_item?: any[];
    product_bundle?: any[];
}
/** 商品行（OS ScanOrderOrderProduct 结构性子集） */
export interface ScanOrderOrderProduct extends ScanOrderOrderProductIdentity {
    order_detail_id: number | null;
    num: number;
    product_sku: ScanOrderProductSku;
    /** enrich 输出兼容字段；运行时规格权威源为 product_sku.option */
    product_option_item?: any[];
    selling_price: string;
    original_price: string;
    tax_fee: string;
    is_charge_tax: number;
    discount_list: any[];
    product_bundle: any[];
    metadata: Record<string, any>;
    note?: string;
    product_title?: Record<string, any>;
}
/** OS Order/SalesSummary 汇总结构 */
export interface ScanOrderSummary {
    product_quantity: number;
    product_original_amount: string;
    product_amount: string;
    product_expect_amount: string;
    product_tax_fee: string;
    shipping_fee: string;
    shipping_tax_fee: string;
    tax_fee: string;
    surcharge_fee: string;
    discount_amount: string;
    deposit_amount: string;
    expect_amount: string;
    total_amount: string;
    amount_gap: string;
    rounding_amount: string;
    pay_service_charge_amount: string;
    tax_title?: string;
    tax_rate?: number;
    [key: string]: any;
}
/** tempOrder（OS ScanOrderTempOrder 结构性子集） */
export interface ScanOrderTempOrder {
    order_id: number | null;
    order_number: string;
    shop_order_number: string;
    shop_full_order_number?: string;
    type: string;
    business_code: string;
    platform: string;
    sales_channel: string;
    order_sales_channel: string;
    status: string;
    payment_status: string;
    shipping_status: string;
    customer_id: number | null;
    customer_name: string;
    country_calling_code: string;
    phone: string;
    email: string;
    is_price_include_tax: number;
    tax_title: string;
    tax_country_code: string;
    currency_code: string;
    currency_symbol: string;
    currency_format: string;
    is_deposit: number;
    deposit_amount: string;
    shop_discount: string;
    surcharge_fee: string;
    note: string;
    schedule_date: string;
    created_at: string;
    products: ScanOrderOrderProduct[];
    bookings: any[];
    payments: any[];
    surcharges: any[];
    discount_list: any[];
    relation_forms: any[];
    contacts: any[];
    /**
     * 联系人信息：与 OS 真源（OrderModule）一致，缺失时为 `null`，有值时必须是对象。
     * 不再使用空数组表示空，提交链路也按 object|null 处理（详见 OS TEMP_ORDER_FIELDS_SUMMARY.md）。
     */
    contacts_info: Record<string, any> | null;
    holder: Record<string, any> | null;
    metadata: Record<string, any>;
    summary?: ScanOrderSummary;
    [key: string]: any;
}
/** 销售详情（来自 parseSalesResponse） */
export interface ISalesDetailHeader {
    order_id: number | string | null;
    order_number?: string;
    shop_order_number?: string;
    status?: string;
    payment_status?: string;
    shipping_status?: string;
    customer_id?: number | string | null;
    customer_name?: string;
    country_calling_code?: string;
    phone?: string;
    email?: string;
    metadata?: Record<string, any> | null;
    total_amount?: string | number;
    [key: string]: any;
}
export interface ISalesBooking {
    schedule_event_id?: number | null;
    booking_id?: string;
    appointment_status?: string;
    status?: string;
    start_date?: string;
    start_time?: string;
    end_date?: string;
    end_time?: string;
    duration?: number;
    resources?: any[];
    product?: any;
    detail?: any;
    parent_id?: number | null;
    product_uid?: string;
    metadata?: Record<string, any> | null;
    relation_id?: number | string | null;
    [key: string]: any;
}
export interface ISalesPayment {
    amount: string;
    origin_amount?: string;
    rounding_amount?: string;
    status?: string;
    payment_time?: string | null;
    type?: string;
    code?: string;
    name?: string;
    [key: string]: any;
}
export interface ISalesSurcharge {
    amount?: string;
    type?: string;
    name?: Record<string, string>;
    [key: string]: any;
}
export interface ISalesDetailCustomer {
    id: number | string | null;
    name: string;
    phone?: string;
    email?: string;
    country_calling_code?: string;
    [key: string]: any;
}
export interface ISalesDetail {
    header: ISalesDetailHeader;
    products: ScanOrderOrderProduct[];
    bookings: ISalesBooking[];
    rootBooking: ISalesBooking | null;
    bookingsByProductUid: Record<string, ISalesBooking[]>;
    payments: ISalesPayment[];
    surcharges: ISalesSurcharge[];
    discount_list: any[];
    customer: ISalesDetailCustomer | null;
    summary: Record<string, any>;
    raw: Record<string, any>;
}
/**
 * 赠品候选选项（来自评估器的 giftOptions 字段）。
 */
export interface SalesSdkGiftOption {
    product_id: number;
    product_variant_id: number;
}
/**
 * GiftSelect Host 请求 context（OS → SDK）。
 *
 * @example
 * giftSelectBridge.request({ strategyId, strategyName, giftCount, giftOptions, sourceProductIds })
 */
export interface SalesSdkGiftSelectContext {
    strategyId: string;
    strategyName: string | Record<string, string>;
    giftCount: number;
    giftOptions: SalesSdkGiftOption[];
    /** 触发此赠品的主商品 metadata.unique_identification_number 列表 */
    sourceProductIds: string[];
    /** edit：购物车重选赠品，单候选也弹窗 */
    mode?: 'add' | 'edit';
    /** 预填已选（购物车重选） */
    initialChoices?: SalesSdkGiftSelectChoice[];
    /** legacy 弹窗 prefill 用（完整 enrich 行） */
    _selectedOriginGifts?: Array<ScanOrderOrderProduct & Record<string, any>>;
}
/** CartSkuCard Gift 行展示数据（与 legacy formatGiftData 对齐） */
export interface SalesSdkCartGiftData {
    isShow: boolean;
    totalCount: number;
    selectedGifts: Array<{
        id: number | string;
        title: string;
        image?: string;
    }>;
    _selectedOriginGifts?: SalesSdkCartItemView[];
}
/** GiftSelect 弹窗回传：用户最终选择的 (variant + 数量) 列表 */
export interface SalesSdkGiftSelectChoice {
    product_id: number;
    product_variant_id: number;
    quantity: number;
    /**
     * 弹窗内已加载的商品快照（confirm 时复用，避免重复 `/shop/product/query`）。
     * 仅内存传递，不会写入 tempOrder。
     */
    _productSnapshot?: Record<string, any>;
}
/**
 * GiftSelect resolver 返回值。
 *
 * @example
 * return { products: [giftProduct], bookings: [giftBooking] };
 */
export interface SalesSdkGiftSelectResult {
    products: Array<Partial<ScanOrderOrderProduct>>;
    bookings?: Record<string, any>[];
}
/**
 * 未满足的促销策略（购物车底部 alert 渲染源）。
 */
export interface SalesSdkUnfulfilledPromotion {
    strategyId: string;
    strategyName: string | Record<string, string>;
    actionType: string;
    needQuantity: number;
    currentQuantity: number;
    requiredQuantity: number;
    eligibleProducts: SalesSdkGiftOption[];
    strategyMetadata?: any;
    display?: {
        text: string | Record<string, string>;
        type: string;
    };
}
/** 商品卡促销标签（appendPromotionTags 写入 `_promotionTags`） */
export interface SalesSdkPromotionTag {
    text: string | Record<string, string>;
    type: string;
    strategyId?: string;
}
/** 上次 applyPromotion 计算出的赠品操作 diff */
export interface SalesSdkLastGiftActions {
    toAdd: Array<{
        strategyId: string;
        strategyName: string | Record<string, string>;
        giftCount: number;
        giftOptions: SalesSdkGiftOption[];
        sourceProductIds: string[];
    }>;
    toReduce: Array<{
        strategyId: string;
        items: Array<{
            uid: string;
            currentQuantity: number;
            newQuantity: number;
        }>;
    }>;
    toRemove: string[];
}
/** OS CustomerModule 选中客户（结构性子集） */
export interface ICustomer {
    id: string | number;
    name?: string;
    phone?: string;
    email?: string;
    country_calling_code?: string;
    [key: string]: any;
}
/**
 * OS Order 模块协议字段视图（OrderCustomerView 结构性 alias）。
 * 这些字段会随订单提交到后端；customer_id 与 OS OrderTempOrder 保持 number | null。
 */
export interface OrderCustomerView {
    customer_id: number | null;
    customer_name: string;
    phone: string;
    email: string;
    country_calling_code: string;
}
/**
 * 写入下单客户的协议字段；customer_id 必填（string id 调用方需自行 Number() 转型），
 * 其余字段缺省视为「清空」。
 */
export interface OrderCustomerPatch {
    customer_id: number | null;
    customer_name?: string;
    phone?: string;
    email?: string;
    country_calling_code?: string;
}
/**
 * `bookingTicket:onOrderCustomerChange` 事件 payload；清空时整体为 null。
 */
export interface OrderCustomerChangePayload {
    patch: OrderCustomerView;
    snapshot: ICustomer | null;
}
export interface IPaginationInfo {
    page: number;
    pageSize: number;
    total: number;
    totalPages: number;
}
export interface ICustomerListResponse {
    list: ICustomer[];
    total: number;
    page?: number;
    pageSize?: number;
}
export interface IGetCustomerListParams {
    skip?: number;
    num?: number;
    search?: string;
    [key: string]: any;
}
/** 商品列表条目（OS ProductData，UI 只用一小部分字段） */
export interface ProductData {
    id: number;
    title?: string;
    cover?: string;
    duration?: number;
    product_resource?: any;
    variants?: any[];
    bundles?: any[];
    options?: any[];
    [key: string]: any;
}
/** OS BookingTicket 加载商品参数 */
export interface ILoadProductsParams {
    category_ids?: number[];
    product_ids?: number[];
    collection?: number | string[];
    schedule_date?: string;
    customer_id?: number;
    menu_list_ids?: number[];
    schedule_datetime?: string;
    with_count?: string[];
    with_schedule?: number;
    extension_type?: string[];
    status?: string;
}
export interface ILoadProductDetailParams extends Omit<ILoadProductsParams, 'product_ids'> {
    product_id: number;
}
export interface IScanResult {
    status: 'success' | 'fail';
    scanType: string;
    scanCode: string;
    result: any;
}
/** Order.updateOrderProduct 入参 */
export interface UpdateOrderProductParams {
    product_id: number | null;
    product_variant_id: number;
    updates: Partial<ScanOrderOrderProduct>;
    unique_identification_number?: string;
    /** @deprecated use unique_identification_number / metadata.unique_identification_number */
    identity_key?: string;
    product_sku?: ScanOrderProductSku;
    /** @deprecated 读规格请用 product_sku.option */
    product_option_item?: any[];
    product_bundle?: any[];
    /** 与商品行 1:1 关联的 booking；传则替换 tempOrder.bookings 中对应项（OS updateOrderProduct）。 */
    booking?: Record<string, any>;
    /**
     * 预约时间 / 时长变更后允许 OS 使用本次报价覆盖已落库订单行历史价。
     *
     * @example
     * await cart.updateItem({
     *   product_id: 1,
     *   product_variant_id: 0,
     *   updates: { selling_price: '6.00', metadata: { source_product_price: '6.00' } },
     *   booking: { duration: 2 },
     *   allow_booking_reprice: true,
     * });
     */
    allow_booking_reprice?: boolean;
}
/** Order.updateOrderProductQuantity 入参；行定位语义与 updateOrderProduct / removeProductFromOrder 一致 */
export interface UpdateOrderProductQuantityParams extends ScanOrderOrderProductIdentity {
    num: number;
}
/** @deprecated 使用 UpdateOrderProductParams */
export declare type UpdateProductInOrderParams = UpdateOrderProductParams;
/** OS BaseSales.scanPromotionCode 返回 */
export interface BaseSalesScanCodeResult {
    isAvailable: boolean;
    type?: 'server' | string;
    unavailableReason?: string;
}
export interface BaseSalesQuotationDurationConfig {
    type: string;
    value: number;
    flexible_config?: {
        is_enable_minimum_duration?: 0 | 1;
        warning_threshold?: number;
        block_threshold?: number;
    };
}
export interface BaseSalesCalculateProductBookingPriceParams {
    product: Record<string, any>;
    booking?: {
        start_date?: string;
        start_time?: string;
        end_date?: string;
        end_time?: string;
        [key: string]: any;
    };
    duration?: BaseSalesQuotationDurationConfig;
    customer_id?: number | string;
    fallback_price?: number | string;
    datetime?: string;
    channel?: string;
}
export interface BaseSalesProductBookingPriceSegment {
    start_datetime: string;
    end_datetime?: string;
    time_point: string;
    unit_price: string;
    quantity: number;
    total_price: string;
    quotation_shelf_id: number;
    source: 'quotation' | 'fallback';
}
export interface BaseSalesBundleProductBookingPriceResult {
    bundle_id?: number | string;
    group_id?: number | string;
    bundle_group_id?: number | string;
    bundle_product_id: number | null;
    bundle_variant_id: number;
    unit_price: string;
    total_price: string;
    quantity: number;
    quotation_shelf_id: number;
    source: 'quotation' | 'fallback';
    segments: BaseSalesProductBookingPriceSegment[];
}
export interface BaseSalesProductBookingPriceResult {
    product_id: number | null;
    product_variant_id: number;
    customer_id?: number | string;
    unit_price: string;
    total_price: string;
    quantity: number;
    duration?: BaseSalesQuotationDurationConfig;
    quotation_shelf_id: number;
    segments: BaseSalesProductBookingPriceSegment[];
    product_bundle?: BaseSalesBundleProductBookingPriceResult[];
}
export interface BaseSalesQuotationCustomerScopeInfo {
    quotationCount: number;
    hasCustomerScopedQuotations: boolean;
    allQuotationsCustomerScoped: boolean;
    customerIds: string[];
    customers: Array<Record<string, any>>;
    quotationScopes: Array<{
        quotationId: number;
        quotationName: string;
        customerIds: string[];
        customers: Array<Record<string, any>>;
    }>;
}
export interface BaseSalesPriceRecalculationContextChange {
    previousCustomerId?: number | string | null;
    nextCustomerId?: number | string | null;
    [key: string]: any;
}
/** Order rules hooks（结构性，原生类型来自 OS RulesParamsHooks） */
export interface RulesParamsHooks {
    getProduct?: (...args: any[]) => any;
    setProduct?: (...args: any[]) => any;
    [key: string]: any;
}
/**
 * OS `LoadSalesDetailParams` 结构性 alias（字段命名与 Order/types 一致，勿自行发明映射）。
 */
export interface SalesSdkLoadSalesDetailParams {
    orderId?: number | string;
    orderNumber?: string;
    externalSaleNumber?: string;
    external_sale_number?: string;
    /**
     * 已由上游搜索接口拿到的销售详情。
     * 传入后 OS 会跳过按 id 远端查询，直接复用详情 hydrate 流程。
     */
    preloadedSalesDetail?: Record<string, any>;
    forceRemote?: boolean;
    merge?: boolean;
}
/** 子预约状态机转移动作（对齐 OS BookingTicket BookingTransitionAction） */
export declare type BookingTransitionAction = 'confirm' | 'reject' | 'arrive' | 'start' | 'complete' | 'cancel' | 'no_show' | 'reschedule';
/** 子预约状态转移入参 */
export interface TransitionChildBookingParams {
    schedule_event_id: number | string;
    action: BookingTransitionAction;
}
/**
 * OS BaseSales.submitSalesOrder 入参（结构性 alias，与 BaseSalesImpl 一致）。
 */
export interface SalesSdkSubmitSalesOrderParams {
    payments?: Record<string, any>[];
    paymentStatus?: string;
    smallTicketDataFlag?: number;
    enhancePayload?: (payload: Record<string, any>, ctx: Record<string, any>) => Record<string, any>;
}
/** SDK 提交行为选项，仅控制前端提交前流程，不透传给 OS submitSalesOrder。 */
export interface SalesSdkSubmitOptions {
    /** 仅特定业务按钮显式开启 holder 必填确认，默认不校验。 */
    validateHolder?: boolean;
}
export interface AddTimePlanLine {
    product_id: string | number;
    product_title?: string;
    product_add_schedule_time: number;
    num: number;
    price: number;
    _originalProduct?: unknown;
}
export interface ResolveBestAddTimePlanResult {
    available: boolean;
    unavailableReason?: 'NO_PRODUCTS' | 'NO_COVERAGE';
    targetMinutes: number;
    coveredMinutes: number;
    totalPrice: number;
    lines: AddTimePlanLine[];
}
/**
 * BookingTicket OS 模块运行时句柄（极简结构性接口；运行时由 `pisellos.getModule(...)` 返回的实例提供）。
 *
 * 对外（消费方）极少直接消费此引用，但 `useSalesSdk().bookingTicket` 仍提供给高级场景。
 * 实际类型由 OS（@pisell/pisellos）提供，这里仅描述本 SDK 调用到的方法。
 */
export interface BookingTicketHandle {
    name: string;
    store?: {
        customer?: any;
        order?: any;
        products?: any;
        [key: string]: any;
    };
    effectsOn: (event: string, callback: (payload: any) => void) => () => void;
    loadSalesDetail: (orderIdOrParams: number | string | SalesSdkLoadSalesDetailParams) => Promise<ISalesDetail>;
    refreshSalesDetail: (params?: {
        forceRemote?: boolean;
    }) => Promise<ISalesDetail>;
    /**
     * 更新当前预约的 appointment_status。
     * 数据全部从 OrderModule.tempOrder 取（order_id / metadata / bookings），
     * schedule id 优先 `metadata.appointment_booking_parent_schedule_id`，
     * 否则使用 `parent_id === 0` 的 root booking 的 `schedule_event_id`。
     * 失败时回滚本地 bookings 的 appointment_status 并抛出。
     */
    setBookingStatus: (status: string) => Promise<any>;
    /**
     * 子预约状态机转移（POST /schedule/booking-transition/{schedule_event_id}）。
     * 按 schedule_event_id 定位子预约，body `{ action }`；成功后刷新销售详情。
     *
     * @example
     * await bookingTicket.transitionChildBooking({ schedule_event_id: 301, action: 'start' });
     */
    transitionChildBooking: (params: TransitionChildBookingParams) => Promise<any>;
    getSalesOrder: () => ISalesDetail | null;
    getOrderHeader: () => ISalesDetailHeader | null;
    getBookings: () => ISalesBooking[];
    getRootBooking: () => ISalesBooking | null;
    getChildBookingsByProductUid: (productUid: string) => ISalesBooking[];
    getPayments: () => ISalesPayment[];
    getSurcharges: () => ISalesSurcharge[];
    getTempOrder: () => ScanOrderTempOrder | null;
    getOrderProducts: () => ScanOrderOrderProduct[];
    getDiscountList: () => any[];
    getSummary: () => Promise<ScanOrderSummary | null>;
    getCart?: () => SalesSdkCartView;
    getCustomer?: () => ICustomer | null;
    getProductCatalog?: () => SalesSdkProductCatalogView;
    /**
     * 读取 OS 已缓存的 Pico OpenData 配置。
     *
     * @example
     * const openData = await bookingTicket.getOpenData?.();
     */
    getOpenData?: () => unknown | Promise<unknown>;
    addNewOrder: () => Promise<ScanOrderTempOrder>;
    restoreOrder: () => Promise<ScanOrderTempOrder>;
    /**
     * 运行时切换 tempOrder 是否写入 localStorage（OS BaseSales → OrderModule）。
     * SalesSdk 默认 false；legacy ticketBooking 不传时 OS 侧仍为 true。
     */
    setEnableTempOrderPersist?: (enabled: boolean) => void;
    /** 当前是否启用 tempOrder localStorage 持久化。 */
    isTempOrderPersistEnabled?: () => boolean;
    /**
     * 仅清空 tempOrder 的 products / bookings / discount_list（保留客户、备注等）。
     * OS OrderModule.clearOrderCartLines；编辑态会同步清空内存 salesDetail 对应视图。
     */
    clearOrderCartLines: () => Promise<ScanOrderTempOrder>;
    replaceTempOrder?: (tempOrder: ScanOrderTempOrder, options?: {
        recalculateSummary?: boolean;
        persist?: boolean;
        saveDraft?: boolean;
    }) => Promise<ScanOrderTempOrder>;
    destroy: () => Promise<void>;
    /**
     * 将商品 catalog / 详情选择回调转为 addProductToOrder 入参（OS BaseSales 提供）。
     */
    transformBaseProductToOrderProduct: (params: {
        payload: Record<string, any>;
        fallbackProductId?: number | string | null;
        sourceProduct?: ProductData | Record<string, any> | null;
        sourceItem?: ProductData | Record<string, any> | null;
    }) => (Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity) | null;
    /**
     * OS `OrderModule.addProductToOrder`：把商品行写入 tempOrder.products，
     * 第二参 `booking` 存在时同步生成 tempOrder.bookings 项并通过 `createLinkedProductAndBooking`
     * 自动改写 booking.product_uid / product.booking_uid，保证商品行与 booking 一一对应。
     *
     * `booking` 字段集严格对齐 OS `TEMP_ORDER_FIELDS_SUMMARY.md` Bookings 章节；
     * SDK 端推荐通过 `transformDetailToProductAndBooking` 生成 `(product, booking)` 输入，
     * 不要自行拼装 `_extend` 字段写入这里。
     */
    addProductToOrder: (product: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity, booking?: Record<string, any>) => Promise<ScanOrderOrderProduct[]>;
    updateOrderProduct: (params: UpdateOrderProductParams) => Promise<ScanOrderOrderProduct[]>;
    updateOrderProducts?: (paramsList: UpdateOrderProductParams[]) => Promise<ScanOrderOrderProduct[]>;
    updateOrderProductQuantity: (params: UpdateOrderProductQuantityParams) => Promise<ScanOrderOrderProduct[]>;
    removeProductFromOrder: (identity: ScanOrderOrderProductIdentity) => Promise<ScanOrderOrderProduct[]>;
    /** 批量删除购物车行，末尾仅一次促销重算（合并预约行删除/减数量场景） */
    removeProductsFromOrder?: (identities: ScanOrderOrderProductIdentity[]) => Promise<ScanOrderOrderProduct[]>;
    setOrderProductLineNote: (identity: ScanOrderOrderProductIdentity, note: string) => Promise<ScanOrderOrderProduct[]>;
    updateTempOrderNote: (note: string) => string;
    /**
     * 写入整单优惠金额（tempOrder.shop_discount）。
     * OS 内部会做 Decimal 标准化：负数归零、保留 2 位小数；返回标准化后的字符串。
     */
    updateTempOrderShopDiscount: (amount: string | number) => string;
    /**
     * 写入联系人信息（tempOrder.contacts_info）。
     * OS 内部防御：非对象/数组都归 `null`，只接对象或 null。返回最终写入的对象或 null。
     * 实际由 BaseSalesImpl.updateTempOrderContactsInfo 提供（与 OS Order 模块同名，
     * 与 BaseSales 既有 updateTempOrderNote 命名风格一致）。
     */
    updateTempOrderContactsInfo: (contactsInfo: Record<string, any> | null) => Record<string, any> | null;
    scanPromotionCode: (code: string, customerId?: number) => Promise<BaseSalesScanCodeResult>;
    loadDiscountConfig?: (params?: {
        customerId?: number;
        action?: 'create' | 'edit';
    }) => Promise<{
        productList?: Record<string, any>[];
        discountList?: any[];
    }>;
    bestDiscount?: (cb?: (result: any) => void) => Promise<{
        productList?: Record<string, any>[];
        discountList?: any[];
    }>;
    calculateProductBookingPrice?: (params: BaseSalesCalculateProductBookingPriceParams) => Promise<BaseSalesProductBookingPriceResult>;
    calculateProductBookingPrices?: (paramsList: BaseSalesCalculateProductBookingPriceParams[]) => Promise<BaseSalesProductBookingPriceResult[]>;
    getQuotationCustomerScopeInfo?: () => BaseSalesQuotationCustomerScopeInfo;
    shouldRecalculateProductBookingPricesForContextChange?: (params: BaseSalesPriceRecalculationContextChange) => boolean;
    setDiscountSelected: (params: {
        discountId: number;
        isSelected: boolean;
    }) => Promise<void>;
    submitSalesOrder: <T = any>(params?: SalesSdkSubmitSalesOrderParams) => Promise<T>;
    /**
     * 注入促销评估器（默认由 SalesSdkProvider 从 `appHelper.utils.promotionEvaluator` 自动注入）。
     * 业务侧一般不直接调用。
     */
    setPromotionEvaluator?: (evaluator: any | null) => void;
    /**
     * 注入赠品选择 resolver。SDK 默认通过 GiftSelect host bridge 注入，业务侧一般不直接调用。
     * resolver 返回完整 OrderProduct 列表（含 metadata._giftInfo 标记）。
     */
    setGiftSelectResolver?: (resolver: ((ctx: SalesSdkGiftSelectContext) => Promise<Array<Partial<ScanOrderOrderProduct>> | SalesSdkGiftSelectResult | null>) | null) => void;
    /**
     * 为商品目录追加促销标签。新版 OS 由 BaseSales/BookingTicket 统一提供；
     * 旧版 OS 缺失时 SDK 会回退到本地兼容实现。
     */
    appendPromotionTags?: <T extends Record<string, any>>(products: T[]) => T[];
    /** 主动触发一次促销重算（一般写路径会自动触发）。 */
    applyPromotion?: () => Promise<void>;
    /** 上一次促销计算输出的未满足促销提示（购物车底部 alert 渲染源）。 */
    getUnfulfilledPromotions?: () => SalesSdkUnfulfilledPromotion[];
    /** 上一次促销计算输出的赠品差异化操作 diff。 */
    getLastGiftActions?: () => SalesSdkLastGiftActions | null;
    loadProducts: (params?: ILoadProductsParams, options?: {
        callback?: (r: any) => void;
        subscriberId?: string;
    }) => Promise<ProductData[]>;
    /**
     * 获取加时商品列表，返回 OS 商品 catalog 原始结构。
     *
     * @example
     * const products = await bookingTicket.getAddTimeProducts?.({ schedule_date: '2026-06-16' });
     */
    getAddTimeProducts?: (params?: ILoadProductsParams) => Promise<ProductData[]>;
    /** 取消 /product/query WS 订阅（与 loadProducts 的 subscriberId 配对） */
    unsubscribeProductQuery?: (subscriberId?: string) => void;
    loadProductDetail: (params: ILoadProductDetailParams, options?: {
        callback?: (r: any) => void;
        subscriberId?: string;
    }) => Promise<ProductData | undefined>;
    /**
     * 只读查询单商品详情：不写 productCatalog、不触发 onProductsLoaded。
     * 旧版 pisellos 无此方法时，购物车编辑预约行会回退 loadProductDetail。
     */
    queryProductDetail?: (params: ILoadProductDetailParams, options?: {
        callback?: (r: any) => void;
        subscriberId?: string;
    }) => Promise<ProductData | undefined>;
    getProductByIds: (ids: number[]) => Promise<ProductData[]>;
    setActiveCustomer: (customer: ICustomer | null) => void;
    getActiveCustomer: () => ICustomer | null;
    setSelectedCustomerById: (id: string | number) => void;
    getCustomers: () => ICustomer[];
    getCustomerById: (id: string | number) => ICustomer | null;
    clearCustomers: () => void;
    addCustomerToFirst: (customer: ICustomer) => void;
    getCustomerList: (params?: IGetCustomerListParams) => Promise<ICustomerListResponse>;
    changeCustomerPage: (page: number, pageSize?: number) => Promise<ICustomerListResponse>;
    loadMoreCustomers: () => Promise<ICustomerListResponse>;
    resetAndLoadCustomers: (params?: IGetCustomerListParams) => Promise<ICustomerListResponse>;
    /** OS 同步 getter（CustomerModule.getPaginationInfo 暴露），可选；缺失时回退到默认分页 */
    getCustomerPaginationInfo?: () => IPaginationInfo;
    setOrderCustomer?: (customer: ICustomer | null) => void;
    getOrderCustomer?: () => OrderCustomerView | null;
    getOrderCustomerSnapshot?: () => ICustomer | null;
    clearOrderCustomer?: () => void;
    /** 挂载原生扫码枪 / NFC 桥接（global.peripheralsResult）；须在 scanGlobalListener 等之前调用。 */
    initPeripheralsListener?: () => void;
    scanGlobalListener: (cb: (data: IScanResult) => void) => () => void;
    scanCustomerListener: (cb: (data: IScanResult) => void) => () => void;
    scanUniversalListener: (cb: (data: IScanResult) => void, key: string) => () => void;
    activateCamera: (data?: Record<string, any>) => void;
    enableAllScanListeners: () => void;
    disableAllScanListeners: () => void;
    /**
     * pubsub 全局扫码入口：搜索 + 业务分发；bridge 由 SalesSdk 注入 uiHosts / cart / action。
     */
    handleGlobalScanCode?: (code: string, bridge?: Record<string, any>) => Promise<{
        status: 'success' | 'pending' | 'cancelled' | 'failed';
        kind?: string;
        reason?: string;
        meta?: {
            count?: number;
        };
    }>;
    loadBookingConfig?: (params?: Record<string, any>) => Promise<Record<string, any> | null>;
    loadBookingResources?: (params?: {
        date?: string;
        bookingIds?: number[];
    }) => Promise<any[]>;
    initBookingContext?: (params?: {
        bookingConfigParams?: Record<string, any>;
        date?: any;
        loadResources?: boolean;
        bookingIds?: number[];
        forceRefresh?: boolean;
    }) => Promise<{
        bookingConfig: Record<string, any> | null;
        resourcesOrigin: any[];
        resourcesOriginMap: Record<string, any>;
        date: string | null;
    }>;
    /** 是否已具备与入参等价的 BookingContext（命中则 init 不再打接口）。 */
    isBookingContextReady?: (params?: {
        bookingConfigParams?: Record<string, any>;
        date?: any;
        loadResources?: boolean;
        bookingIds?: number[];
    }) => boolean;
    setBookingConfig?: (config: Record<string, any> | null) => void;
    getBookingConfig?: () => Record<string, any> | null;
    setResources?: (resources: any[] | null | undefined) => void;
    getResourcesOrigin?: () => any[];
    getResourcesOriginMap?: () => Record<string, any>;
    setBookingDate?: (date: any) => void;
    getBookingDate?: () => string | null;
    /** 取商品当前可选资源列表（与 info2 `getResourceByIds` 等价，含三特性）。 */
    getResourcesForProduct?: (product: any, options?: {
        extraResources?: Array<{
            form_id: number | string;
            id: number;
        }>;
    }) => any[];
    /** 拼装 cacheItem 的 _extend / _data（资源 / 容量 / timeObj），与 info2 `getProductExtend` 等价。 */
    getProductExtend?: (cacheItem: any, extra?: Record<string, any>) => any;
    /** 取资源不可用原因（结构化 enum + params）。 */
    getResourceErrors?: (resource: any, cacheItem: any) => SalesSdkResourceError[];
    decideAddProduct?: (item: any, options?: Record<string, any>) => {
        action: 'add' | 'requiresDetail' | 'requiresBookingEdit' | 'reloadCatalog';
        cacheItem?: any;
        payload?: Record<string, any>;
    };
    decideAfterDetail?: (cacheItem: any, options?: Record<string, any>) => {
        action: 'add' | 'requiresBookingEdit';
        cacheItem?: any;
        payload?: Record<string, any>;
    };
    /** @deprecated 请用 decideAddProduct */
    decideAutoClose?: (item: any, options?: Record<string, any>) => {
        autoClose: boolean;
        cacheItem?: any;
    };
    getIsEject?: (item: any, type?: 'select' | 'detail') => 0 | 1;
    getIsOnlySession?: (item: any) => boolean;
    buildRequiresDetailPayload?: (item: any, options?: Record<string, any>) => SalesSdkAddProductRequiresDetailPayload;
    transformDetailToProductAndBooking?: (input: {
        item: any;
        cacheItem?: any;
        detailResult?: {
            e: any;
            extension_type?: any;
            detail?: any;
        };
        options?: Record<string, any>;
    }) => {
        product: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity;
        booking?: Record<string, any>;
        cacheItem: any;
    };
    /** 已加车 order line + booking → 资源编辑抽屉 cacheItem（OS 官方反查）。 */
    buildCacheItemFromOrderLine?: (input: {
        product: ScanOrderOrderProduct;
        booking: Record<string, any>;
        sourceProduct?: Record<string, any> | null;
    }) => Record<string, any>;
    /** 已加车普通商品 order line → SkuDetailModal edit cacheItem（OS 官方反查）。 */
    buildNormalProductCacheItemFromOrderLine?: (input: {
        product: ScanOrderOrderProduct;
        sourceProduct?: Record<string, any> | null;
    }) => Record<string, any>;
    setOtherParams: (params: Record<string, any>, options?: {
        cover?: boolean;
    }) => Promise<void>;
    getOtherParams: () => Promise<Record<string, any>> | Record<string, any>;
    resolveBestAddTimePlan?: (addTimeProducts: any[], targetMinutes: number) => ResolveBestAddTimePlanResult | null;
    /**
     * 将加时商品作为独立商品行绑定到已有 booking。
     *
     * @example
     * await bookingTicket.addAddTimeProductToBooking?.({ booking, product, product_add_schedule_time: 30 });
     */
    addAddTimeProductToBooking?: (input: SalesSdkAddAddTimeProductInput) => Promise<ScanOrderOrderProduct[]>;
    /**
     * 批量将加时商品作为独立商品行绑定到已有 booking。
     *
     * @example
     * await bookingTicket.addAddTimeProductsToBooking?.({ booking, products: [{ product }] });
     */
    addAddTimeProductsToBooking?: (input: SalesSdkAddAddTimeProductsInput) => Promise<ScanOrderOrderProduct[]>;
}
/**
 * `cart.addProduct` 返回 `status='requiresDetail'` 时的 payload。
 * UI 拿到后自行打开 Info2（或新版 saleDetail）详情弹窗，弹窗回调后再调 `cart.confirmDetail`。
 */
export interface SalesSdkAddProductRequiresDetailPayload {
    item: ProductData | Record<string, any>;
    showConfig: {
        option: boolean;
        session: boolean;
        variant: boolean;
        package: boolean;
        number: boolean;
    };
    isOnlySession: boolean;
    isEject: 0 | 1;
    customerId?: number | string;
    date: string | null;
    productData: ProductData | Record<string, any>;
}
/**
 * `requiresBookingEdit` 时 UI 打开资源 / 时间编辑抽屉所需 payload。
 */
export interface SalesSdkRequiresBookingEditPayload {
    cacheItem: any;
    customerId?: number | string;
    date: string | null;
    /**
     * 已加车行「编辑资源」：强制打开抽屉，忽略 cacheItem.autoClose。
     * 加车链路（requiresBookingEdit）不传此字段；autoClose=true 时自动 confirm 跳过抽屉。
     */
    forceOpen?: boolean;
    /**
     * 购物车跨日编辑：先开抽屉，再在 Host 内异步展开 `_extend.items`。
     * 加车 / requiresBookingEdit 链路不传此字段。
     */
    deferMultiDayExpand?: boolean;
    /** 跨日判定回退（与 editCartLineBooking 一致） */
    sourceProduct?: Record<string, any> | null;
    /** 加车链路 catalog 商品，供 Host 补拉报价 */
    catalogProduct?: Record<string, any> | null;
}
/**
 * `cart.addProduct` 判别式返回值。
 *
 * - `added`：两关均通过，已写入 OS tempOrder。
 * - `requiresDetail`：需打开规格 / SKU 弹窗，callback 后调 `cart.confirmDetail`。
 * - `requiresBookingEdit`：规格已就绪，需打开资源 / 时间抽屉，确认后调 `cart.confirmBookingEdit`。
 */
export declare type SalesSdkAddProductResult = {
    status: 'added';
    products: ScanOrderOrderProduct[];
} | {
    status: 'cancelled';
} | {
    status: 'requiresDetail';
    payload: SalesSdkAddProductRequiresDetailPayload;
} | {
    status: 'requiresBookingEdit';
    payload: SalesSdkRequiresBookingEditPayload;
};
/**
 * `cart.confirmDetail` 判别式返回值（规格选完后可能仍需资源编辑）。
 */
export declare type SalesSdkConfirmDetailResult = {
    status: 'added';
    products: ScanOrderOrderProduct[];
} | {
    status: 'requiresBookingEdit';
    payload: SalesSdkRequiresBookingEditPayload;
};
/**
 * `cart.confirmDetail` 输入：UI 拿到 Info2 callback 的 `(e, extension_type, detail)` 后回传。
 */
/** 跨日日期弹窗确认结果（对齐 ticketBooking MultiDayTimeSelectModal callback） */
export interface SalesSdkMultiDaySelectResult {
    startDate: string;
    endDate: string;
    duration: number;
    /** 跨日预约开始营业时间；BigSale 默认来自 getData('operating_day_boundary').time。 */
    startTime?: string;
    /** 跨日预约结束营业时间；默认与 startTime 一致。 */
    endTime?: string;
}
/** `openMultiDaySelect` Host 入参 */
export interface SalesSdkOpenMultiDaySelectPayload {
    productName?: string;
    /** 日历默认锚点日 YYYY-MM-DD */
    defaultStartDate?: string | null;
}
/** `openHolderSelect` Host 入参 */
export interface SalesSdkOpenHolderSelectPayload {
    cacheItem: any;
    maxSelectedCount?: number;
    customerId?: number | string;
}
/** 「创建并添加一次性商品」弹窗回传数据（与 booking CustomiseItemModal 字段对齐） */
export interface SalesSdkCustomProductInput {
    productName: string;
    vouchersApplicable: boolean;
    priceType: 'sell' | 'deduction';
    priceValue: string;
    quantity: number;
}
/**
 * 添加加时商品输入。
 *
 * @example
 * await cart.addAddTimeProduct({
 *   booking,
 *   product,
 *   num: 1,
 *   price: '10.00',
 *   product_add_schedule_time: 30,
 * });
 */
export interface SalesSdkAddAddTimeProductInput {
    /** 当前已有 booking，必须带 metadata.unique_identification_number。 */
    booking: SalesSdkCartBookingView | Record<string, any>;
    /** 加时商品原始数据。 */
    product: ProductData & Record<string, any>;
    /** 本次添加数量，缺省为 1。 */
    num?: number;
    /** 本次加时商品价格。 */
    price?: number | string;
    /** 加时时长，单位分钟；最终写入商品行 metadata.product_add_schedule_time。 */
    product_add_schedule_time?: number;
    /** 本次加时方案实际覆盖分钟数，用于同步更新 booking 结束时间与 duration。 */
    coveredMinutes?: number;
    /** 直接写入 booking 的时间补丁，restart 场景使用。 */
    bookingPatch?: {
        start_date?: string;
        start_time?: string;
        end_date?: string;
        end_time?: string;
        duration?: number;
    };
}
/**
 * 批量添加加时商品的单行输入。
 *
 * @example
 * const line: SalesSdkAddAddTimeProductLineInput = { product, product_add_schedule_time: 30 };
 */
export declare type SalesSdkAddAddTimeProductLineInput = Omit<SalesSdkAddAddTimeProductInput, 'booking' | 'coveredMinutes' | 'bookingPatch'>;
/**
 * 批量添加加时商品输入。
 *
 * @example
 * await cart.addAddTimeProducts({
 *   booking,
 *   products: [{ product, product_add_schedule_time: 30 }],
 * });
 */
export interface SalesSdkAddAddTimeProductsInput {
    /** 当前已有 booking，必须带 metadata.unique_identification_number。 */
    booking: SalesSdkCartBookingView | Record<string, any>;
    /** 一次性写入购物车的加时商品行。 */
    products: SalesSdkAddAddTimeProductLineInput[];
    /** 本次加时方案实际覆盖分钟数，用于同步更新 booking 结束时间与 duration。 */
    coveredMinutes?: number;
    /** 直接写入 booking 的时间补丁，restart 场景使用。 */
    bookingPatch?: SalesSdkAddAddTimeProductInput['bookingPatch'];
}
export interface SalesSdkConfirmDetailInput {
    item: ProductData | Record<string, any>;
    detailResult: {
        e: any;
        extension_type?: any;
        detail?: any;
    };
    options?: {
        quantity?: number;
        notShowToast?: boolean;
        /** 跨日弹窗确认后的区间（规格弹窗之后注入） */
        multiDayRange?: SalesSdkMultiDaySelectResult;
    };
}
/**
 * `cart.confirmBookingEdit` 输入：资源 / 时间抽屉确认后的 cacheItem。
 */
export interface SalesSdkConfirmBookingEditInput {
    cacheItem: any;
    options?: {
        quantity?: number;
        note?: string;
    };
}
/**
 * 页面级 UI Host：由 SalesSdkProvider 注入，供 `cart.addProductWithFlow` 编排弹窗链。
 *
 * 实现方在页面内可用 Hook 组装后传入；Provider 只持有函数引用，不 import 具体弹窗组件。
 */
export interface SalesSdkUIHosts {
    /**
     * `requiresDetail` 时打开规格 / SKU / 称重弹窗。
     * 用户取消时返回 `null`。
     */
    openProductDetail?: (payload: SalesSdkAddProductRequiresDetailPayload) => Promise<SalesSdkConfirmDetailInput['detailResult'] | null>;
    /**
     * `requiresBookingEdit` 时打开资源 / 时间编辑抽屉。
     * 用户取消时返回 `null`；确认时返回编辑后的 cacheItem。
     */
    openBookingEdit?: (payload: SalesSdkRequiresBookingEditPayload) => Promise<any | null>;
    /**
     * 规格弹窗确认后、跨日商品须选日期区间（对齐 ticketBooking `MultiDayTimeSelectModal`）。
     */
    openMultiDaySelect?: (payload: SalesSdkOpenMultiDaySelectPayload) => Promise<SalesSdkMultiDaySelectResult | null>;
    /**
     * 加车前 Holder 选择（对齐 ticketBooking `selectHolderModal`）。
     */
    openHolderSelect?: (payload: SalesSdkOpenHolderSelectPayload) => Promise<number[] | null>;
}
/**
 * `cart.addProductWithFlow` 返回值。
 *
 * - `added`：完整链路结束并已写入 OS。
 * - `cancelled`：用户在 Host 弹窗/抽屉中取消。
 * - `requiresDetail` / `requiresBookingEdit`：决策命中但对应 Host 未配置，交由调用方处理。
 */
/** 已加车行「编辑资源」结果 */
export declare type SalesSdkEditCartLineBookingResult = {
    status: 'updated';
    products: ScanOrderOrderProduct[];
} | {
    status: 'cancelled';
};
/** 已加车普通商品行「编辑 SKU」结果 */
export declare type SalesSdkEditCartLineProductResult = SalesSdkEditCartLineBookingResult | {
    status: 'removed';
    products?: ScanOrderOrderProduct[];
};
/** 购物车行点击编辑（自动分流 booking / 普通商品） */
export declare type SalesSdkEditCartLineResult = SalesSdkEditCartLineBookingResult | Extract<SalesSdkEditCartLineProductResult, {
    status: 'removed';
}>;
export declare type SalesSdkAddProductWithFlowResult = {
    status: 'added';
    products: ScanOrderOrderProduct[];
} | {
    status: 'cancelled';
} | {
    status: 'requiresDetail';
    payload: SalesSdkAddProductRequiresDetailPayload;
} | {
    status: 'requiresBookingEdit';
    payload: SalesSdkRequiresBookingEditPayload;
};
/** `cart.addProductWithFlow` 调用参数（含防抖 / Toast） */
export interface SalesSdkAddProductWithFlowOptions {
    type?: 'select' | 'detail';
    quantity?: number;
    note?: string;
    /** 连点合并窗口毫秒，默认 200（首击立即加车，窗口内后续点击合并追加）；0 表示每次独立立即加车 */
    debounceMs?: number;
    /** 为 true 时不展示加车 Toast */
    notShowToast?: boolean;
    /**
     * 防抖层已决策的 cacheItem；传入后 cart.addProduct 跳过第二次 decideAddProduct。
     * @internal 由 createAddProductWithFlowDebounced 注入，业务调用方勿传。
     */
    preparedCacheItem?: any;
}
/**
 * 资源不可用原因（与 OS `BookingContext.ResourceUnavailableReason` 一比一对齐）。
 *
 * i18n 文案不进 OS，UI 拿到 reason + params 后自行渲染，对照表见 `salesSdk/docs.md`。
 */
export declare type SalesSdkResourceUnavailableReason = 'no_product' | 'time_out_of_range' | 'count_out_of_range' | 'resource_unbound';
export interface SalesSdkResourceError {
    reason: SalesSdkResourceUnavailableReason;
    params: {
        labelText?: string;
        startText?: string;
        endText?: string;
        isCrossDay?: boolean;
    };
}
/** SalesSdkProvider 状态机 */
export declare type SalesSdkStatus = 'idle' | 'loading' | 'ready' | 'error';
export interface SalesSdkProviderProps {
    /** 多实例区分；与 ticketBooking 共享同一 osKey 时自动复用其 BookingTicket 实例 */
    osKey: string;
    /** 透传给 OS BookingTicket 的 businessCode */
    businessCode?: string;
    /**
     * 拉取 board config 的参数（`/core/board/management/config`），
     * 挂载后由 SalesSdkProvider 调 `bookingTicket.initBookingContext`。
     */
    bookingConfigParams?: Record<string, any>;
    /** 是否在 Provider 挂载后自动初始化 BookingContext，默认 true */
    autoInitBookingContext?: boolean;
    /** 透传给 OS 注册时的 otherParams（platform / type / channel / dineInConfig 等） */
    otherParams?: Record<string, any>;
    /** 业务自定义 rules hooks，否则用 OrderModule 默认 */
    rulesHooks?: RulesParamsHooks;
    /**
     * 给定 orderId 且 autoBootstrap !== false 时，挂载后自动 loadSalesDetail；
     * 不传则不会自动 createNew，避免空 osKey 误建 tempOrder。
     */
    orderId?: number;
    /** 已查询到的销售详情对象，用于详情首屏免二次查询。 */
    preloadedSalesDetail?: Record<string, any>;
    /** 默认 true */
    autoBootstrap?: boolean;
    /**
     * 挂载后是否先 restore 清空 OS 残留 tempOrder / localStorage（与 demo reset 一致），
     * 再 recalcSummary；有 orderId 时在 restore 之后 loadDetail。默认 true。
     * 与 ticketBooking 共享 osKey 且需保留进行中订单时可设为 false。
     */
    autoRestoreOnInit?: boolean;
    /**
     * PaymentModal 全额支付完成后是否自动 restoreOrder。
     * 默认 true，用于卖票页/新建单在结账完成后清空临时订单；订单详情页可设为 false 保留详情态。
     */
    restoreOrderAfterPaidCheckout?: boolean;
    /**
     * Provider 卸载时是否销毁当前 BookingTicket 上下文。
     * 默认 false，避免误销毁与 ticketBooking / 预加载弹窗共享的 osKey；短生命周期详情实例可显式开启。
     */
    destroyOnUnmount?: boolean;
    /**
     * 页面级弹窗 / 抽屉 Host（规格弹窗、资源编辑等）。
     * 未传字段时 Provider 使用实例级内置 Host；传入字段覆盖对应内置 Host。
     */
    uiHosts?: Partial<SalesSdkUIHosts>;
    /**
     * LCE 预约商品详情 Host（`pisell1.handleOpenProductModal`）。
     * Provider 会与实例级 normalHost 组合为 `openProductDetail`。
     */
    legacyOpenProductDetail?: import('./demo/hosts/legacyOpenProductDetail').CreateLegacyOpenProductDetailHostDeps;
    /** 是否开启 tempOrder 主副屏同步，默认关闭，由业务入口按需启用。 */
    enableTempOrderSync?: boolean;
    /**
     * 是否将 tempOrder 写入 localStorage（OS OrderModule.persistTempOrder）。
     * SalesSdk 默认 false：订单仅驻留内存，避免污染 ticketBooking 等同 osKey 的本地缓存。
     * ticketBooking 等 legacy 入口不传时 OS 侧仍为 true。
     */
    enableTempOrderPersist?: boolean;
    /**
     * 页面/Tab 是否处于激活态（与 ticketBooking isActive 对齐）。
     * 为 true 时挂载或重新激活原生外设扫码桥接；默认 true。
     */
    isActive?: boolean;
    /**
     * 是否订阅 app.pubsub 原生扫码（`nativeScanResult`）并调用 OS handleGlobalScanCode。
     * 默认 false，业务入口（如 BookingPos）显式开启。
     */
    enableGlobalScanListener?: boolean;
    /**
     * 每次 loadProducts 都会合并的固定参数（如 dine_in 弹窗固定餐牌 menu_list_ids），
     * 优先级高于 boardConfig 推导值，低于单次 load(params) 显式传入。
     */
    defaultProductLoadParams?: ILoadProductsParams;
    children: React.ReactNode;
}
/** UI 视图：购物车行（多源 enrichment 输出，仅活在 React 内存） */
export interface SalesSdkCartItemView extends ScanOrderOrderProduct {
    /** 给 OS removeProductFromOrder/updateOrderProduct 的稳定 identity */
    _identity: ScanOrderOrderProductIdentity;
    _extend: {
        booking: ISalesBooking | null;
        /** 合并 booking 展示行展开后的真实 booking/product 来源，仅 UI 层使用 */
        mergedBookingSources?: SalesSdkMergedBookingSource[];
        /** 标记当前商品行来自合并 booking 展示代表行，仅 UI 层使用 */
        isMergedBookingLine?: boolean;
        /** 合并 booking 展示数量，仅 UI 层使用 */
        displayQuantity?: number;
    };
    title: string;
    cover: string;
    variant_title: string;
    bundle_titles: string[];
    option_titles: string[];
    product_option_string?: string;
    note: string;
    duration?: number;
    product_resource?: any;
    capacity?: any;
    start_at: string | null;
    end_at: string | null;
    resource_id?: number | string | null;
    /** 主商品促销赠品行（CartSkuCard Gift 组件） */
    giftData?: SalesSdkCartGiftData | null;
    _promotionTags?: SalesSdkPromotionTag[];
    promotions?: SalesSdkPromotionTag[];
    _isGiftPromotion?: boolean;
    _giftInfo?: Record<string, any>;
}
/** Holder 展示字段（Cart enrich 注入，不写 OS） */
export interface SalesSdkHolderDisplayFields {
    holder_id?: string | number | Array<string | number> | null;
    holderOptions?: Array<{
        id: string | number;
        label: string;
    }>;
    /** 与 ProductCard cartSkuCard 契约对齐 */
    holders?: Array<{
        id: string | number;
        label: string;
    }>;
    isFormSubject?: boolean;
    holderType?: string;
    holderMaxCount?: number;
}
/** 合并 booking 展示行对应的真实 OS 行，写操作需展开到这些来源。 */
export interface SalesSdkMergedBookingSource {
    booking: ISalesBooking;
    product: SalesSdkCartItemView;
    identity: ScanOrderOrderProductIdentity;
}
/** UI 视图：booking 行（平铺，附带关联商品 + Holder 展示 enrich） */
export interface SalesSdkCartBookingView extends ISalesBooking, SalesSdkHolderDisplayFields {
    _extend: {
        product: SalesSdkCartItemView | null;
        /** 当前 booking 绑定的加时商品行，已从 cart.items 中剔除。 */
        addTimeProduct?: SalesSdkCartItemView[];
        /** OS BookingTicket 计算出的旧 ticketBooking 加时入口可用性。 */
        canAddTime?: boolean;
        /** 合并 booking 展示行展开后的真实 booking/product 来源，仅 UI 层使用 */
        mergedFrom?: SalesSdkMergedBookingSource[];
        /** 标记当前 booking 为合并展示代表行，仅 UI 层使用 */
        isMergedBookingLine?: boolean;
        /** 合并 booking 展示数量，仅 UI 层使用 */
        displayQuantity?: number;
        /** 合并 booking 展示行聚合出的 holder id，仅 UI 层使用 */
        mergedHolderIds?: Array<string | number>;
    };
}
/** UI 视图：客户卡片（selected → tempOrder fallback） */
export interface SalesSdkCustomerView {
    id: number | string;
    name: string;
    phone?: string;
    email?: string;
    country_calling_code?: string;
    cover?: string;
    isWalkIn: boolean;
}
/** UI 视图：BookingTicketImpl.getCart 输出（与 OS buildCartView 结构一致） */
export interface SalesSdkCartView {
    bookings: SalesSdkCartBookingView[];
    items: ScanOrderOrderProduct[];
}
/** UI 视图：BookingTicketImpl.getProductCatalog 输出 */
export interface SalesSdkProductCatalogView {
    products: ProductData[];
}
export interface SalesSdkContextValue {
    bookingTicket: BookingTicketHandle | null;
    osKey: string;
    status: SalesSdkStatus;
    error: Error | null;
    isReady: boolean;
    shop_full_order_number: string;
    /**
     * 直读 OS tempOrder 原貌（提交契约，UI 不污染）。
     *
     * SDK 顶层维护单一真源；Cart / Customer 等子 Provider 通过 `useSalesSdk()` 共享，
     * 子 Provider 不再重复持有镜像。子 Provider 的写动作（如 cart action）会在末尾
     * 触发内部 RootRefresh 重新读 OS，保证此字段与 OS 状态一致。
     */
    tempOrder: ScanOrderTempOrder | null;
    /**
     * 服务端 sales 详情（编辑态有，新建态为 null）。
     * 来源同 tempOrder，由 SDK 顶层 Provider 维护。
     */
    salesDetail: ISalesDetail | null;
    loadDetail: (orderIdOrParams: number | SalesSdkLoadSalesDetailParams) => Promise<ISalesDetail>;
    /**
     * 强制走远端拉取销售详情（跳过本地 sqlite 缓存），参数形态与 OS `loadSalesDetail` 一致。
     */
    loadDetailByRemote: (orderId: number) => Promise<ISalesDetail>;
    /**
     * 基于当前 tempOrder.order_id 强制从远端刷新销售详情（转发 OS `refreshSalesDetail`）。
     * 调用前须已 loadDetail / 存在 order_id；成功后同步顶层 `tempOrder` / `salesDetail`。
     * Provider 内部已用 useMemoizedFn 包装，引用稳定。
     */
    refreshSalesDetail: (params?: {
        forceRemote?: boolean;
    }) => Promise<ISalesDetail>;
    /**
     * loadProducts 前确保 boardConfig 已就绪；与 bootstrap `initBookingContext` 同参，
     * 但不强制拉 resources。bootstrap 已完成且 config 命中时会直接跳过。
     */
    ensureBookingConfigForLoad: () => Promise<void>;
    /** 挂载时传入的固定 loadProducts 参数（如弹窗固定餐牌 menu_list_ids）。 */
    defaultProductLoadParams?: ILoadProductsParams;
    /** 与 bootstrap initBookingContext 对齐的 board config 查询参数。 */
    bookingConfigParams?: Record<string, any>;
    createNew: () => Promise<ScanOrderTempOrder>;
    restore: () => Promise<ScanOrderTempOrder>;
    /**
     * 仅清空购物车商品行（products / bookings / discount_list），保留客户与其它订单字段。
     */
    clearCartItemsOnly: () => Promise<ScanOrderTempOrder>;
    /**
     * 清空所有内容并重置购物车（转发 OS restoreOrder，含清客户）。
     */
    clearCartAndReset: () => Promise<ScanOrderTempOrder>;
    destroy: () => Promise<void>;
    /**
     * 变更当前订单的预约状态，详见 BookingTicketHandle.setBookingStatus。
     * Provider 内部已用 useMemoizedFn 包装，引用稳定，可直接放入 useEffect deps。
     */
    setBookingStatus: (status: string) => Promise<any>;
    /**
     * 子预约状态机转移，详见 BookingTicketHandle.transitionChildBooking。
     *
     * @example
     * await sales.transitionChildBooking({ schedule_event_id: 301, action: 'complete' });
     */
    transitionChildBooking: (params: TransitionChildBookingParams) => Promise<any>;
    /**
     * 写入订单备注（tempOrder.note，字符串）。
     * 直接转发到 OrderModule.updateTempOrderNote（同步赋值），写完触发内部 refreshRootSnapshot
     * 让 React 立即拿到新的 tempOrder.note。返回最终写入的字符串。
     * Provider 内部已用 useMemoizedFn 包装，引用稳定，可直接放入 useEffect deps。
     */
    setOrderNote: (note: string) => string;
    /**
     * 写入整单优惠金额（tempOrder.shop_discount）。
     * 直接转发到 BookingTicket.updateTempOrderShopDiscount（OS 内部 Decimal 标准化：
     * 负数归零、保留 2 位小数），写完触发 refreshRootSnapshot 让 React 立即拿到新值。
     * 返回标准化后的字符串（如 5 -> '5.00'）。
     * Provider 内部已用 useMemoizedFn 包装，引用稳定，可直接放入 useEffect deps。
     */
    setShopDiscount: (amount: string | number) => string;
    /**
     * 写入联系人信息（tempOrder.contacts_info）。
     * 直接转发到 BookingTicket.updateTempOrderContactsInfo（OS 内部防御：非对象/数组归 null），
     * 写完触发 refreshRootSnapshot 让 React 立即拿到新值。返回最终写入的对象或 null。
     * Provider 内部已用 useMemoizedFn 包装，引用稳定，可直接放入 useEffect deps。
     */
    setContactsInfo: (contactsInfo: Record<string, any> | null) => Record<string, any> | null;
    /**
     * 激活扫码/二维码相机入口，直接转发到底层 BookingTicket。
     */
    activateCamera: (data?: Record<string, any>) => void;
    /**
     * 打开结账面板：派发 `pisell1.handleOpenPayment`，
     * `baseSalesModuleName` 自动取本 Provider 的 BookingTicket moduleKey（`getBookingTicketKey(osKey)`），
     * 调用方无需感知模块命名规则。
     *
     * 返回值为底层 action callback 的回传结果，便于消费方在结账完成后做后续动作（如刷新详情）。
     * 当宿主环境未注入 `appHelper.utils.action` 时直接抛错。
     */
    openCheckout: (options?: SalesSdkSubmitOptions) => Promise<any>;
    /**
     * 提交销售订单并在成功后从远端刷新详情（与 cart.submit 同 Holder 确认流程）。
     * 用户关闭 Holder 确认弹窗时抛 `HOLDER_CONFIRM_CANCELLED`，不触发 submit / 刷新。
     *
     * @example
     * await sales.submitAndRefresh();
     * await sales.submitAndRefresh({ paymentStatus: 'pending' });
     */
    submitAndRefresh: <T = any>(params?: SalesSdkSubmitSalesOrderParams, options?: SalesSdkSubmitOptions) => Promise<T>;
    /**
     * 读取当前订单折扣列表（转发 OS `BaseSales.getDiscountList`）。
     * 返回克隆数组，避免消费方就地修改污染 OS store。
     */
    getDiscountList: () => any[];
    /**
     * 扫描优惠码（转发 OS `BaseSales.scanPromotionCode`）。
     * 成功后触发顶层 `tempOrder` 快照刷新；返回轻量结果（不含 discountList，需再调 `getDiscountList`）。
     */
    scanPromotionCode: (code: string, customerId?: number) => Promise<BaseSalesScanCodeResult>;
    /**
     * 勾选/取消订单折扣（转发 OS `BaseSales.setDiscountSelected`）。
     * OS 内部会重算 rules、行价与 summary；完成后同步顶层快照。
     */
    setDiscountSelected: (params: {
        discountId: number;
        isSelected: boolean;
    }) => Promise<void>;
    resolveBestAddTimePlan: (addTimeProducts: any[], targetMinutes: number) => ResolveBestAddTimePlanResult | null;
}
export interface SalesSdkProductsContextValue {
    products: ProductData[];
    loading: boolean;
    error: Error | null;
    load: (params?: ILoadProductsParams, options?: {
        subscriberId?: string;
        silent?: boolean;
    }) => Promise<ProductData[]>;
    /**
     * 获取加时商品，并转换为可直接写入订单/购物车的商品行结构。
     *
     * @example
     * const orderProducts = await products.getAddTimeProducts({ schedule_date: '2026-06-16' });
     */
    getAddTimeProducts: (params?: ILoadProductsParams) => Promise<ProductData[]>;
    loadDetail: (params: ILoadProductDetailParams) => Promise<ProductData | undefined>;
    findByIds: (ids: number[]) => Promise<ProductData[]>;
    scanGlobalListener: (cb: (data: IScanResult) => void) => () => void;
    scanCustomerListener: (cb: (data: IScanResult) => void) => () => void;
    scanUniversal: (cb: (data: IScanResult) => void, key: string) => () => void;
    activateCamera: (data?: Record<string, any>) => void;
    enableScan: () => void;
    disableScan: () => void;
}
/** 客户搜索选项：弹窗打开/输入 debounce 等静默刷新时可关闭 Search 按钮 loading */
export interface SalesSdkCustomerSearchOptions {
    /** 是否展示 Search 按钮 loading，默认 true */
    showLoading?: boolean;
}
export interface SalesSdkCustomerContextValue {
    selected: ICustomer | null;
    list: ICustomer[];
    pagination: IPaginationInfo;
    hasMore: boolean;
    loading: boolean;
    loadingMore: boolean;
    searchParams: Record<string, any>;
    select: (customer: ICustomer | null) => void;
    loadList: (params?: IGetCustomerListParams) => Promise<ICustomerListResponse>;
    search: (keyword: string, options?: SalesSdkCustomerSearchOptions) => Promise<ICustomerListResponse>;
    loadMore: () => Promise<ICustomerListResponse>;
    changePage: (page: number, pageSize?: number) => Promise<ICustomerListResponse>;
    addToFirst: (customer: ICustomer) => void;
    clear: () => void;
    loadById: (id: string | number) => ICustomer | null;
}
export interface SalesSdkSummaryContextValue {
    summary: ScanOrderSummary | null;
}
export interface SalesSdkCartContextValue {
    /** 直读 OS tempOrder 原貌（提交契约，UI 不污染） */
    tempOrder: ScanOrderTempOrder | null;
    /** 服务端 sales 详情（编辑态有，新建态为 null） */
    salesDetail: ISalesDetail | null;
    discountList: any[];
    /**
     * 上一次 OS applyPromotion 输出的未满足促销提示。
     * UI（购物车底部 alert）渲染源；客户切换或购物车增减后自动刷新。
     */
    unfulfilledPromotions: SalesSdkUnfulfilledPromotion[];
    /** 上一次 OS applyPromotion 输出的赠品操作 diff（debug 用，UI 一般不消费） */
    lastGiftActions: SalesSdkLastGiftActions | null;
    /** 平铺 booking + 关联商品（透传 OS） */
    bookings: SalesSdkCartBookingView[];
    /** 未关联 booking 的商品行（透传 OS tempOrder.products） */
    items: SalesSdkCartItemView[];
    /**
     * 加车主入口：走 OS `decideAddProduct` 两阶段决策 → `added` | `requiresDetail` | `requiresBookingEdit`。
     */
    addProduct: (product: ProductData & Record<string, any>, options?: {
        type?: 'select' | 'detail';
        quantity?: number;
        note?: string;
    }) => Promise<SalesSdkAddProductResult>;
    /** 规格弹窗 callback 后回灌；可能返回 `requiresBookingEdit`。 */
    confirmDetail: (input: SalesSdkConfirmDetailInput) => Promise<SalesSdkConfirmDetailResult>;
    /** 资源 / 时间抽屉确认后加车。 */
    confirmBookingEdit: (input: SalesSdkConfirmBookingEditInput) => Promise<{
        products: ScanOrderOrderProduct[];
    }>;
    /**
     * 加车编排入口：内部 `addProduct` → uiHosts 弹窗链 → `confirmDetail` / `confirmBookingEdit`。
     * Host 未配置时遇 `requiresDetail` / `requiresBookingEdit` 会直接返回对应 status。
     */
    addProductWithFlow: (product: ProductData & Record<string, any>, options?: SalesSdkAddProductWithFlowOptions) => Promise<SalesSdkAddProductWithFlowResult>;
    /**
     * 添加自定义（一次性）商品：直接写入 tempOrder.products，不走 decideAddProduct 弹窗链。
     */
    addCustomProduct: (input: SalesSdkCustomProductInput) => Promise<ScanOrderOrderProduct[]>;
    /**
     * 添加加时商品：绑定到已有 booking，不新增 booking，不走预约商品弹窗链。
     *
     * @example
     * await addAddTimeProduct({ booking, product, product_add_schedule_time: 30 });
     */
    addAddTimeProduct: (input: SalesSdkAddAddTimeProductInput) => Promise<ScanOrderOrderProduct[]>;
    /**
     * 批量添加加时商品：绑定到已有 booking，并在 OS 层只重算一次购物车。
     *
     * @example
     * await addAddTimeProducts({ booking, products: [{ product, product_add_schedule_time: 30 }] });
     */
    addAddTimeProducts: (input: SalesSdkAddAddTimeProductsInput) => Promise<ScanOrderOrderProduct[]>;
    removeItem: (item: SalesSdkCartItemView | SalesSdkCartBookingView) => Promise<ScanOrderOrderProduct[]>;
    updateItem: (params: UpdateOrderProductParams) => Promise<ScanOrderOrderProduct[]>;
    /** 仅更新购物车行数量；传入 cart item / booking 行与目标数量即可 */
    updateItemQuantity: (item: SalesSdkCartItemView | SalesSdkCartBookingView, num: number) => Promise<ScanOrderOrderProduct[]>;
    setOrderNote: (note: string) => string;
    setLineNote: (identity: ScanOrderOrderProductIdentity, note: string) => Promise<ScanOrderOrderProduct[]>;
    setDiscount: (params: {
        discountId: number;
        isSelected: boolean;
    }) => Promise<void>;
    scanCode: (code: string, customerId?: number) => Promise<BaseSalesScanCodeResult>;
    submit: <T = any>(params?: SalesSdkSubmitSalesOrderParams, options?: SalesSdkSubmitOptions) => Promise<T>;
    recalcSummary: () => Promise<ScanOrderSummary | null>;
    /**
     * 已加车预约行编辑资源/时间：OS 反查 cacheItem → openBookingEdit → updateOrderProduct + booking。
     * 无 booking 的行会抛错；未配置 openBookingEdit 时抛错。
     */
    editCartLineBooking: (item: SalesSdkCartItemView) => Promise<SalesSdkEditCartLineBookingResult>;
    /**
     * 已加车普通商品行编辑 SKU：OS 反查 cacheItem → SkuDetailModal → updateOrderProduct（无 booking）。
     */
    editCartLineProduct: (item: SalesSdkCartItemView) => Promise<SalesSdkEditCartLineProductResult>;
    /**
     * 购物车行点击编辑：booking 行反查 items 后，按 `_extend.booking` 分流
     * `editCartLineBooking` / `editCartLineProduct`。
     */
    editCartLine: (target: SalesSdkCartItemView | SalesSdkCartBookingView) => Promise<SalesSdkEditCartLineResult>;
    /**
     * 主商品赠品行点击：打开 legacy 赠品弹窗并重写该策略赠品。
     *
     * @example
     * await selectGiftForItem(mainCartLine);
     */
    selectGiftForItem: (target: SalesSdkCartItemView | SalesSdkCartBookingView) => Promise<void>;
}
