/**
 * 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';
/** 商品行 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_option_item?: any[];
    product_bundle?: any[];
}
/** 商品行（OS ScanOrderOrderProduct 结构性子集） */
export interface ScanOrderOrderProduct extends ScanOrderOrderProductIdentity {
    order_detail_id: number | null;
    num: number;
    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;
}
/** 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>;
}
/** 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;
}
export interface ILoadProductDetailParams extends Omit<ILoadProductsParams, 'product_ids'> {
    product_id: number;
}
export interface IScanResult {
    status: 'success' | 'fail';
    scanType: string;
    scanCode: string;
    result: any;
}
/** Order.updateProductInOrder 入参 */
export interface UpdateProductInOrderParams {
    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_option_item?: any[];
    product_bundle?: any[];
}
/** OS BaseSales.scanPromotionCode 返回 */
export interface BaseSalesScanCodeResult {
    isAvailable: boolean;
    type?: 'server' | string;
    unavailableReason?: string;
}
/** 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;
    forceRemote?: boolean;
}
/**
 * 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: () => 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>;
    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;
    addNewOrder: () => Promise<ScanOrderTempOrder>;
    restoreOrder: () => Promise<ScanOrderTempOrder>;
    destroy: () => Promise<void>;
    addProductToOrder: (product: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity) => Promise<ScanOrderOrderProduct[]>;
    updateProductInOrder: (params: UpdateProductInOrderParams) => Promise<ScanOrderOrderProduct[]>;
    removeProductFromOrder: (identity: ScanOrderOrderProductIdentity) => Promise<ScanOrderOrderProduct[]>;
    setOrderProductLineNote: (identity: ScanOrderOrderProductIdentity, note: string) => Promise<ScanOrderOrderProduct[]>;
    updateTempOrderNote: (note: string) => string;
    /**
     * 写入整单优惠金额（tempOrder.shop_discount）。
     * OS 内部会做 Decimal 标准化：负数归零、保留 2 位小数；返回标准化后的字符串。
     * 实际由 BaseSalesImpl.updateOrderShopDiscount 提供（命名沿用 OS 既有约定，
     * 与 updateTempOrderNote 不对称属 OS 历史命名，这里如实声明）。
     */
    updateOrderShopDiscount: (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>;
    setDiscountSelected: (params: {
        discountId: number;
        isSelected: boolean;
    }) => Promise<void>;
    submitScanOrder: <T = any>(params?: any) => Promise<T>;
    loadProducts: (params?: ILoadProductsParams, options?: {
        callback?: (r: any) => void;
        subscriberId?: string;
    }) => Promise<ProductData[]>;
    loadProductDetail: (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;
    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;
    setOtherParams: (params: Record<string, any>, options?: {
        cover?: boolean;
    }) => Promise<void>;
    getOtherParams: () => Promise<Record<string, any>> | Record<string, any>;
}
/** SalesSdkProvider 状态机 */
export declare type SalesSdkStatus = 'idle' | 'loading' | 'ready' | 'error';
export interface SalesSdkProviderProps {
    /** 多实例区分；与 ticketBooking 共享同一 osKey 时自动复用其 BookingTicket 实例 */
    osKey: string;
    /** 透传给 OS BookingTicket 的 businessCode */
    businessCode?: string;
    /** 透传给 OS 注册时的 otherParams（platform / type / channel / dineInConfig 等） */
    otherParams?: Record<string, any>;
    /** 业务自定义 rules hooks，否则用 OrderModule 默认 */
    rulesHooks?: RulesParamsHooks;
    /**
     * 给定 orderId 且 autoBootstrap !== false 时，挂载后自动 loadSalesDetail；
     * 不传则不会自动 createNew，避免空 osKey 误建 tempOrder。
     */
    orderId?: number;
    /** 默认 true */
    autoBootstrap?: boolean;
    children: React.ReactNode;
}
/** UI 视图：购物车商品行（透传 OS tempOrder.products） */
export declare type SalesSdkCartItemView = ScanOrderOrderProduct;
/** enrichCartItem(s) 输出的展示层视图（仅 React 内存，非 getCart 默认形态） */
export interface SalesSdkEnrichedCartItemView extends ScanOrderOrderProduct {
    _identity: ScanOrderOrderProductIdentity;
    title: string;
    cover: string;
    variant_title: string;
    bundle_titles: string[];
    option_titles: string[];
    note: string;
    duration?: number;
    product_resource?: any;
    capacity?: any;
    start_at: string | null;
    end_at: string | null;
    resource_id?: number | string | null;
}
/** UI 视图：booking 行（平铺，附带关联商品） */
export interface SalesSdkCartBookingView extends ISalesBooking {
    _extend: {
        product: SalesSdkCartItemView | null;
    };
}
/** 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 输出 */
export interface SalesSdkCartView {
    bookings: SalesSdkCartBookingView[];
    items: SalesSdkCartItemView[];
}
/** 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: (orderId: number) => Promise<ISalesDetail>;
    /**
     * 强制走远端拉取销售详情（跳过本地 sqlite 缓存），参数形态与 OS `loadSalesDetail` 一致。
     */
    loadDetailByRemote: (orderId: number) => Promise<ISalesDetail>;
    /**
     * 基于当前 tempOrder.order_id 强制从远端刷新销售详情（转发 OS `refreshSalesDetail`）。
     * 调用前须已 loadDetail / 存在 order_id；成功后同步顶层 `tempOrder` / `salesDetail`。
     * Provider 内部已用 useMemoizedFn 包装，引用稳定。
     */
    refreshSalesDetail: () => Promise<ISalesDetail>;
    createNew: () => Promise<ScanOrderTempOrder>;
    restore: () => Promise<ScanOrderTempOrder>;
    destroy: () => Promise<void>;
    /**
     * 变更当前订单的预约状态，详见 BookingTicketHandle.setBookingStatus。
     * Provider 内部已用 useMemoizedFn 包装，引用稳定，可直接放入 useEffect deps。
     */
    setBookingStatus: (status: string) => Promise<any>;
    /**
     * 写入订单备注（tempOrder.note，字符串）。
     * 直接转发到 OrderModule.updateTempOrderNote（同步赋值），写完触发内部 refreshRootSnapshot
     * 让 React 立即拿到新的 tempOrder.note。返回最终写入的字符串。
     * Provider 内部已用 useMemoizedFn 包装，引用稳定，可直接放入 useEffect deps。
     */
    setOrderNote: (note: string) => string;
    /**
     * 写入整单优惠金额（tempOrder.shop_discount）。
     * 直接转发到 BookingTicket.updateOrderShopDiscount（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;
    /**
     * 打开结账面板：派发 `pisell1.handleOpenPayment`，
     * `baseSalesModuleName` 自动取本 Provider 的 BookingTicket moduleKey（`getBookingTicketKey(osKey)`），
     * 调用方无需感知模块命名规则。
     *
     * 返回值为底层 action callback 的回传结果，便于消费方在结账完成后做后续动作（如刷新详情）。
     * 当宿主环境未注入 `appHelper.utils.action` 时直接抛错。
     */
    openCheckout: () => Promise<any>;
}
export interface SalesSdkProductsContextValue {
    products: ProductData[];
    loading: boolean;
    error: Error | null;
    load: (params?: ILoadProductsParams, options?: {
        subscriberId?: string;
    }) => 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;
}
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) => 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 {
    discountList: any[];
    /** 平铺 booking + 关联商品（透传 OS） */
    bookings: SalesSdkCartBookingView[];
    /** 未关联 booking 的商品行（透传 OS tempOrder.products） */
    items: SalesSdkCartItemView[];
    addProduct: (input: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity) => Promise<ScanOrderOrderProduct[]>;
    removeItem: (item: SalesSdkCartItemView) => Promise<ScanOrderOrderProduct[]>;
    updateItem: (params: UpdateProductInOrderParams) => Promise<ScanOrderOrderProduct[]>;
    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>() => Promise<T>;
    recalcSummary: () => Promise<ScanOrderSummary | null>;
}
