import { Hono } from 'hono';
import { b1 as ProductInputField } from './product-DXhjLQ_w.js';

interface Clock {
    now(): Date;
    nowMs(): number;
    iso(): string;
    advance(ms: number): void;
    freeze(at?: Date): void;
    unfreeze(): void;
    schedule(at: Date | number, fn: () => void): void;
}

interface IdGen {
    ulid(): string;
    prefixed(prefix: string): string;
    cart(): string;
    cartItem(): string;
    order(): string;
    orderNumber(): string;
    business(): string;
    product(): string;
    variant(): string;
    category(): string;
    collection(): string;
    bundle(): string;
    composite(): string;
    session(): string;
    customer(): string;
    service(): string;
    booking(): string;
    subscription(): string;
    upload(): string;
    conversation(): string;
    message(): string;
    quote(): string;
    fxQuote(): string;
    payment(): string;
    raw(prefix: string): string;
}

type MockEventType = "cart.updated" | "cart.cleared" | "order.created" | "order.payment.captured" | "order.payment.failed" | "order.cancelled" | "order.confirmed" | "subscription.created" | "subscription.cancelled" | "subscription.paused" | "subscription.resumed" | "subscription.renewed" | "booking.created" | "booking.cancelled" | "booking.rescheduled" | "support.message.sent" | "support.message.received" | "auth.session.started" | "auth.session.ended" | "upload.confirmed";
interface MockEvent<T = unknown> {
    id: string;
    type: MockEventType;
    occurred_at: string;
    business_id?: string;
    payload: T;
}
type Handler = (e: MockEvent) => void;
interface MockBus {
    emit(type: MockEventType, payload: unknown, businessId?: string): MockEvent;
    on(type: MockEventType | "*", handler: Handler): () => void;
    history(limit?: number): MockEvent[];
    clear(): void;
}

interface Store<T> {
    get(id: string): T | undefined;
    put(id: string, value: T): T;
    delete(id: string): boolean;
    list(filter?: (t: T) => boolean): T[];
    values(): IterableIterator<T>;
    size(): number;
    reset(): void;
    toJSON(): Record<string, T>;
    loadJSON(data: Record<string, T>): void;
}

interface Session {
    id: string;
    token: string;
    business_id: string;
    customer_id?: string;
    customer_name?: string;
    customer_email?: string;
    customer_phone?: string;
    is_authenticated: boolean;
    created_at: string;
    expires_at: string;
}
interface OtpRequest {
    id: string;
    contact: string;
    code: string;
    expires_at: string;
    attempts: number;
}
interface IdempotencyRecord {
    key: string;
    request_hash: string;
    response: unknown;
    status: number;
    created_at: string;
    expires_at: string;
}
interface MockBusiness {
    id: string;
    name: string;
    handle: string;
    business_type: string;
    email: string;
    default_currency: string;
    default_phone?: string;
    default_address?: string;
    default_offers_table_service: boolean;
    default_accepts_online_orders: boolean;
    image?: string;
    status: string;
    created_at: string;
    updated_at: string;
    created_by: string;
    preferences: Record<string, unknown>;
    is_online_only: boolean;
    enabled_payment_types: string[];
    default_location_settings: Record<string, unknown>;
    country_code?: string;
    timezone?: string;
    metadata?: Record<string, unknown>;
}
interface MockQuantityPricingTier {
    min_quantity: number;
    unit_price: string;
}
interface MockBillingPlan {
    id: string;
    name: string;
    interval: "day" | "week" | "month" | "year";
    interval_count: number;
    price: string;
    currency: string;
    trial_period_days?: number;
}
interface MockProduct {
    id: string;
    business_id: string;
    name: string;
    slug: string;
    description?: string;
    product_type: string;
    base_price: string;
    currency: string;
    image?: string;
    images: string[];
    is_available: boolean;
    category_ids: string[];
    collection_ids: string[];
    add_on_ids: string[];
    variant_ids: string[];
    tags?: string[];
    calories?: number;
    allergies?: string[];
    ingredients?: string[];
    pairings?: string[];
    is_signature?: boolean;
    is_new?: boolean;
    /** Override for the auto-derived render hint. */
    render_hint?: "food" | "physical" | "general";
    /** Display mode hint (card opens modal, page is a link). Storefronts can override. */
    display_mode?: "card" | "page";
    /** For digital products — how the SDK renders fulfilment UI. */
    digital_product_type?: "download" | "license" | "event_ticket" | "access_pass" | "gift_code";
    /** For wholesale products — quantity-pricing tiers. */
    quantity_pricing?: MockQuantityPricingTier[];
    /** For services — duration unit (drives Rental/Accommodation/Lease cards). */
    duration_unit?: "minutes" | "hours" | "days" | "nights" | "weeks" | "months" | "years";
    /** For schedule services — duration in minutes (presence implies non-subscription service). */
    duration_minutes?: number;
    /** For subscription services — billing plans. */
    billing_plans?: MockBillingPlan[];
    /**
     * Per-product customer input fields. Surfaced as ProductView.input_fields
     * on the wire so the SDK's product UIs can render the right input
     * controls (file upload for prescriptions, date for DOB, signature for
     * consent, etc.). Same shape the Rust backend already emits
     * (`src/salesman/models/view.rs::ProductView.input_fields`).
     */
    input_fields?: ProductInputField[];
    metadata?: Record<string, unknown>;
    created_at: string;
    updated_at: string;
}
interface MockCategory {
    id: string;
    business_id: string;
    name: string;
    slug: string;
    description?: string;
    image?: string;
    product_ids: string[];
    display_order: number;
    is_active: boolean;
    created_at: string;
    updated_at: string;
}
interface MockCollection {
    id: string;
    business_id: string;
    name: string;
    slug: string;
    description?: string;
    product_ids: string[];
    is_active: boolean;
    created_at: string;
    updated_at: string;
}
interface MockCart {
    id: string;
    business_id: string;
    session_id?: string;
    customer_id?: string;
    customer_name?: string;
    customer_email?: string;
    customer_phone?: string;
    customer_address?: string;
    items: MockCartItem[];
    subtotal: string;
    tax_amount: string;
    tax_rate?: string;
    service_charge: string;
    service_charge_rate?: string;
    total_discounts: string;
    total_price: string;
    delivery_fee: string;
    total_items: number;
    currency: string;
    applied_discount_ids: string[];
    applied_discount_codes: string[];
    status: string;
    source: string;
    channel: string;
    created_at: string;
    updated_at: string;
    expires_at: string;
}
interface MockCartItem {
    id: string;
    cart_id: string;
    item_id: string;
    variant_id?: string;
    line_key: string;
    quantity: number;
    price: string;
    add_ons_price: string;
    configuration: {
        type: string;
        [k: string]: unknown;
    };
    applied_discount_ids: string[];
    item_discount_amount: string;
    scheduled_start?: string;
    scheduled_end?: string;
    staff_id?: string;
    resource_id?: string;
    service_status?: "pending" | "confirmed" | "completed" | "cancelled";
    confirmation_code?: string;
    special_instructions?: string;
    customer_inputs?: {
        field_id: string;
        field_name?: string;
        field_type?: string;
        value: unknown;
    }[];
    billing_plan_id?: string;
    metadata?: Record<string, unknown>;
    created_at: string;
    updated_at: string;
}
interface MockOrder {
    id: string;
    business_id: string;
    user_friendly_id: string;
    channel: string;
    status: string;
    payment_state: string;
    order_type: string;
    customer_id?: string;
    customer_name?: string;
    customer_email?: string;
    customer_phone?: string;
    delivery_address?: string;
    delivery_fee: string;
    subtotal: string;
    tax_amount: string;
    service_charge: string;
    total_discounts: string;
    total_price: string;
    currency: string;
    items: unknown[];
    applied_discount_ids: string[];
    applied_discount_codes: string[];
    payment_reference?: string;
    pickup_time?: string;
    metadata?: Record<string, unknown>;
    created_at: string;
    updated_at: string;
}
interface MockSubscription {
    id: string;
    business_id: string;
    customer_id: string;
    product_id: string;
    status: "active" | "paused" | "cancelled" | "expired";
    next_renewal_at: string;
    paused_at?: string;
    cancelled_at?: string;
    current_period_start: string;
    current_period_end: string;
    created_at: string;
    updated_at: string;
}
interface MockBooking {
    id: string;
    business_id: string;
    customer_id?: string;
    service_id: string;
    service_name: string;
    start_time: string;
    end_time: string;
    status: "confirmed" | "cancelled" | "completed" | "rescheduled";
    participant_count: number;
    confirmation_code: string;
    order_id?: string;
    created_at: string;
    updated_at: string;
}
interface MockService {
    id: string;
    business_id: string;
    name: string;
    description?: string;
    duration_minutes: number;
    price: string;
    is_available: boolean;
}
interface MockUpload {
    id: string;
    business_id: string;
    filename: string;
    mime_type: string;
    size_bytes: number;
    upload_url: string;
    public_url: string;
    status: "pending" | "confirmed";
    created_at: string;
}
interface MockConversation {
    id: string;
    business_id: string;
    customer_id?: string;
    messages: MockChatMessage[];
    created_at: string;
    updated_at: string;
}
interface MockChatMessage {
    id: string;
    conversation_id: string;
    sender_type: "customer" | "agent" | "system";
    content_type: "text" | "image" | "file";
    content: string;
    created_at: string;
}
interface MockQuote {
    id: string;
    business_id: string;
    product_id: string;
    status: "fresh" | "stale" | "expired";
    total_price: string;
    expires_at: string;
    created_at: string;
}
interface MockFxLock {
    id: string;
    base_currency: string;
    pay_currency: string;
    rate: number;
    base_amount: string;
    pay_amount: string;
    expires_at: string;
    created_at: string;
}
interface MockActivityEvent {
    id: string;
    business_id: string;
    session_id?: string;
    event_type: string;
    payload: Record<string, unknown>;
    created_at: string;
}
interface MockAddOn {
    id: string;
    business_id: string;
    name: string;
    is_multiple_allowed: boolean;
    is_required: boolean;
    is_mutually_exclusive: boolean;
    min_selections?: number;
    max_selections?: number;
    created_at: string;
    updated_at: string;
    options: MockAddOnOption[];
}
interface MockAddOnOption {
    id: string;
    add_on_id: string;
    business_id: string;
    name: string;
    default_price?: string;
    description?: string;
    is_required: boolean;
    is_mutually_exclusive: boolean;
    created_at: string;
    updated_at: string;
}
interface MockProductAddOnLink {
    product_id: string;
    add_on_id: string;
}
interface MockVariantAxis {
    id: string;
    business_id: string;
    product_id: string;
    name: string;
    display_order: number;
    affects_recipe: boolean;
    values: MockVariantAxisValue[];
    created_at: string;
    updated_at: string;
}
interface MockVariantAxisValue {
    id: string;
    business_id: string;
    axis_id: string;
    name: string;
    display_order: number;
    color_hex?: string;
    created_at: string;
    updated_at: string;
}
interface MockVariant {
    id: string;
    product_id: string;
    business_id: string;
    name: string;
    sku?: string;
    price_adjustment: string;
    component_multiplier: string;
    is_default: boolean;
    is_active: boolean;
    axis_value_ids: string[];
    /** Per-variant images, when authored. Optional — most fixtures omit it. */
    images?: string[];
    created_at: string;
    updated_at: string;
}
interface MockBundle {
    id: string;
    business_id: string;
    product_id: string;
    name: string;
    slug: string;
    description?: string;
    pricing_type: "fixed" | "percentage_discount" | "fixed_discount";
    bundle_price?: string;
    discount_value?: string;
    product_ids: string[];
    created_at: string;
    updated_at: string;
}
interface MockComposite {
    id: string;
    business_id: string;
    product_id: string;
    base_price: string;
    pricing_mode: "additive" | "highest_per_group" | "highest_overall" | "tiered";
    min_order_quantity?: number;
    max_order_quantity?: number;
    groups: {
        id: string;
        name: string;
        min: number;
        max: number;
        component_ids: string[];
    }[];
    created_at: string;
    updated_at: string;
}
interface MockTag {
    id: string;
    business_id: string;
    name: string;
    slug: string;
    color?: string;
    icon?: string;
    description?: string;
    tag_group?: string;
    sort_order: number;
    usage_count: number;
    created_at: string;
    updated_at: string;
}
interface MockTaxonomy {
    id: string;
    business_id: string;
    name: string;
    slug: string;
    parent_id?: string;
    path: string[];
    attribute_template_ids: string[];
    created_at: string;
    updated_at: string;
}
interface MockKnowledgeArticle {
    id: string;
    business_id: string;
    title: string;
    slug: string;
    content: string;
    category?: string;
    tags: string[];
    created_at: string;
    updated_at: string;
}
interface MockAttributeDef {
    id: string;
    business_id: string;
    namespace: string;
    name: string;
    slug: string;
    description?: string;
    attribute_type: string;
    options?: string[];
    unit?: string;
    is_required: boolean;
    is_filterable: boolean;
    visibility: "admin_only" | "storefront_read" | "public";
    display_order: number;
    applies_to: "product" | "variant" | "both" | "category" | "collection" | "all";
    created_at: string;
    updated_at: string;
}
interface StateRegistry {
    businesses: Store<MockBusiness>;
    products: Store<MockProduct>;
    categories: Store<MockCategory>;
    collections: Store<MockCollection>;
    carts: Store<MockCart>;
    orders: Store<MockOrder>;
    subscriptions: Store<MockSubscription>;
    bookings: Store<MockBooking>;
    services: Store<MockService>;
    sessions: Store<Session>;
    otps: Store<OtpRequest>;
    idempotency: Store<IdempotencyRecord>;
    uploads: Store<MockUpload>;
    conversations: Store<MockConversation>;
    quotes: Store<MockQuote>;
    fxLocks: Store<MockFxLock>;
    activity: Store<MockActivityEvent>;
    addOns: Store<MockAddOn>;
    productAddOns: Store<MockProductAddOnLink>;
    variantAxes: Store<MockVariantAxis>;
    variants: Store<MockVariant>;
    bundles: Store<MockBundle>;
    composites: Store<MockComposite>;
    tags: Store<MockTag>;
    taxonomies: Store<MockTaxonomy>;
    knowledgeArticles: Store<MockKnowledgeArticle>;
    attributeDefs: Store<MockAttributeDef>;
}

interface AuthService {
    resolveSession(token: string | null): Session | null;
    ensureSession(token: string | null): Session;
    requestOtp(contact: string): {
        otp_id: string;
        expires_at: string;
        code_hint?: string;
    };
    verifyOtp(contact: string, code: string): Session;
    logout(token: string): void;
    updateProfile(token: string, profile: {
        name?: string;
        email?: string;
        phone?: string;
    }): Session;
    status(token: string | null): {
        is_authenticated: boolean;
        account_id?: string;
        user_type: "customer" | "guest";
        session_expires_at?: number;
        /** @deprecated Kept for SDK back-compat; production lens does not return this. */
        session?: Session;
    };
}

interface BusinessService {
    primary(): MockBusiness;
    byHandle(handle: string): MockBusiness;
    byDomain(domain: string): MockBusiness;
    settings(businessId: string): unknown;
    locations(businessId: string): unknown[];
    hours(businessId: string): unknown[];
}

interface CatalogueService {
    snapshot(businessId: string): {
        categories: unknown[];
        products: unknown[];
        add_ons: unknown[];
        is_complete: boolean;
        total_available: number;
    };
    listProducts(businessId: string, opts?: {
        page?: number;
        limit?: number;
        category_id?: string;
        collection_id?: string;
    }): unknown;
    getProduct(productId: string): unknown;
    getProductVariants(productId: string): MockVariant[];
    getProductVariantAxes(productId: string): MockVariantAxis[];
    getProductVariantById(productId: string, variantId: string): MockVariant;
    findProductVariant(productId: string, properties: Record<string, string>): MockVariant | null;
    getProductAddOns(productId: string): MockAddOn[];
    getProductAttributes(productId: string): MockAttributeDef[];
    listCategories(businessId: string): MockCategory[];
    getCategory(id: string): MockCategory;
    getCategoryProducts(id: string): unknown[];
    getCategoryAttributes(id: string): MockAttributeDef[];
    listCollections(businessId: string): MockCollection[];
    getCollection(id: string): MockCollection;
    getCollectionProducts(id: string): unknown[];
    getCollectionAttributes(id: string): MockAttributeDef[];
    listBundles(businessId: string): MockBundle[];
    getBundle(id: string): MockBundle;
    listComposites(businessId: string): MockComposite[];
    getComposite(id: string): MockComposite;
    getCompositeByProduct(productId: string): MockComposite | null;
    calculateCompositePrice(id: string, body: unknown): unknown;
    listTaxonomies(businessId: string): MockTaxonomy[];
    searchTaxonomies(businessId: string, q: string): MockTaxonomy[];
    getTaxonomy(id: string): MockTaxonomy;
    getTaxonomyAttributes(id: string): MockAttributeDef[];
    getTaxonomyPath(id: string): string[];
    listAttributes(businessId: string): MockAttributeDef[];
    listTags(businessId: string): MockTag[];
    listKnowledgeArticles(businessId: string): MockKnowledgeArticle[];
    searchKnowledgeBase(businessId: string, q: string): MockKnowledgeArticle[];
    listPropertyFacets(businessId: string): unknown[];
    listDeals(businessId: string): unknown[];
    listOnSale(businessId: string): unknown[];
    validateDiscount(code: string, businessId: string): unknown;
    getProductDeals(productId: string): unknown[];
    getCategoryDeals(id: string): unknown[];
    getCollectionDeals(id: string): unknown[];
    createQuote(businessId: string, body: unknown): unknown;
    getQuote(id: string): unknown;
    refreshQuote(id: string): unknown;
}

interface CustomerInputValue {
    field_id: string;
    field_name?: string;
    field_type?: string;
    value: unknown;
}
interface AddItemInput {
    item_id: string;
    variant_id?: string;
    quantity: number;
    add_on_options?: string[];
    bundle_selections?: BundleSelectionInput[];
    composite_selections?: ComponentSelectionInput[];
    scheduled_start?: string;
    scheduled_end?: string;
    staff_id?: string;
    resource_id?: string;
    special_instructions?: string;
    customer_inputs?: CustomerInputValue[];
    billing_plan_id?: string;
    quote_id?: string;
    metadata?: Record<string, unknown>;
}
interface BundleSelectionInput {
    component_id: string;
    variant_id?: string;
    quantity: number;
    scheduled_start?: string;
    scheduled_end?: string;
}
interface ComponentSelectionInput {
    component_id?: string;
    source_product_id?: string;
    source_stock_id?: string;
    source_type?: "product" | "stock" | "add_on" | "standalone";
    quantity?: number;
}

interface CartService {
    get(session: Session): MockCart;
    getItems(session: Session): MockCartItem[];
    getCount(session: Session): number;
    getTotal(session: Session): string;
    addItem(session: Session, body: AddItemInput): unknown;
    updateQuantity(session: Session, cartItemId: string, quantity: number): unknown;
    removeItem(session: Session, cartItemId: string): unknown;
    clear(session: Session): unknown;
    applyCoupon(session: Session, code: string): unknown;
    removeCoupon(session: Session): unknown;
    toUICart(cart: MockCart): unknown;
    resolveCart(session: Session): MockCart;
}

interface CheckoutService {
    process(session: Session, body: CheckoutBody): CheckoutResult;
    authorize(body: {
        order_id: string;
        otp?: string;
        pin?: string;
    }): {
        status: string;
        order_id: string;
    };
}
interface CheckoutBody {
    cart_id: string;
    location_id?: string;
    customer: {
        name: string;
        email: string;
        phone: string;
        notes?: string;
        save_details?: boolean;
    };
    order_type: string;
    address_info?: Record<string, unknown>;
    payment_method: string;
    mobile_money_details?: {
        phone_number: string;
        provider: string;
    };
    special_instructions?: string;
    metadata?: Record<string, unknown>;
    pay_currency?: string;
    fx_quote_id?: string;
}
interface CheckoutResult {
    order_id: string;
    order_number: string;
    payment_status: string;
    payment_reference?: string;
    requires_authorization: boolean;
    authorization_type?: "otp" | "pin" | "phone" | "birthday" | "address";
    next_action: {
        type: "none";
    } | {
        type: "redirect";
        authorization_url: string;
    } | {
        type: "authorization";
        authorization_type: string;
        display_text?: string;
    };
    provider?: string;
    authorization_url?: string;
    display_text?: string;
    /** Bearer token used for guest order access (lookup `/orders/{id}?token=...`). */
    bill_token?: string;
    /** Stripe-style client secret for direct PaymentIntent confirmation. */
    client_secret?: string;
    /** Stripe publishable key (mock value in dev). */
    public_key?: string;
}

interface OrderService {
    list(session: Session, opts?: {
        limit?: number;
        status?: string;
    }): {
        items: MockOrder[];
        pagination: unknown;
    };
    /** Cross-business listing for the Cimplify Link surface. */
    listByCustomer(customerId: string, opts?: {
        limit?: number;
        offset?: number;
        status?: string;
    }): MockOrder[];
    get(orderId: string): MockOrder;
    getPaymentStatus(orderId: string): {
        order_id: string;
        payment_state: string;
        status: string;
    };
    cancel(orderId: string, reason?: string): MockOrder;
    updateCustomer(orderId: string, customer: {
        name?: string;
        email?: string;
        phone?: string;
    }): MockOrder;
    verifyPayment(orderId: string): {
        order_id: string;
        payment_state: string;
        status: string;
        verified: boolean;
    };
}

interface SubscriptionService {
    list(session: Session): MockSubscription[];
    get(id: string): MockSubscription;
    cancel(id: string): MockSubscription;
    pause(id: string): MockSubscription;
    resume(id: string): MockSubscription;
    skipNext(id: string): MockSubscription;
}

interface SchedulingService {
    listServices(businessId: string): MockService[];
    getService(id: string): MockService;
    getSlots(serviceId: string, opts?: {
        date?: string;
    }): unknown[];
    checkSlot(serviceId: string, start: string, end: string): {
        is_available: boolean;
    };
    getServiceAvailability(serviceId: string): unknown;
    getCustomerBookings(session: Session): unknown[];
    getBooking(id: string): MockBooking;
    cancelBooking(id: string, reason?: string): MockBooking;
    rescheduleBooking(body: {
        booking_id: string;
        new_start_time: string;
        new_end_time: string;
    }): MockBooking;
}

interface InventoryService {
    productStock(productId: string): {
        product_id: string;
        location_id?: string;
        stock_level: number;
        in_stock: boolean;
    };
    variantStock(variantId: string): {
        variant_id: string;
        location_id?: string;
        stock_level: number;
        in_stock: boolean;
    };
    productAvailability(productId: string, quantity?: number): {
        product_id: string;
        quantity: number;
        is_available: boolean;
    };
    variantAvailability(variantId: string, quantity?: number): {
        variant_id: string;
        quantity: number;
        is_available: boolean;
    };
    /**
     * Reserve stock for a cart item. No-op for product types that don't track
     * inventory (services, digital). Throws on insufficient stock.
     */
    reserve(productId: string, variantId: string | undefined, quantity: number): void;
    /** Release a previously-reserved quantity (e.g. when a line is removed). */
    release(productId: string, variantId: string | undefined, quantity: number): void;
}

interface FxService {
    getRate(from: string, to: string): {
        from: string;
        to: string;
        rate: number;
        updated_at: string;
    };
    lockQuote(body: {
        base_currency: string;
        pay_currency: string;
        base_amount: string;
    }): MockFxLock;
}

interface PlacesService {
    autocomplete(body: {
        query: string;
        country?: string;
    }): {
        predictions: unknown[];
    };
    details(body: {
        place_id: string;
    }): unknown;
}

interface MockDeliveryOption {
    rate_id: string | null;
    name: string;
    description?: string;
    fee: string;
    currency: string;
    free_delivery_applied: boolean;
    free_over_amount?: string;
    eta_min_minutes?: number;
    eta_max_minutes?: number;
    is_default: boolean;
    details: Record<string, unknown>;
}
interface DeliveryService {
    getFee(opts: {
        lat?: number;
        lng?: number;
        address?: string;
        cart_total?: string;
    }): {
        fee: string;
        currency: string;
        estimated_minutes: number;
        provider: string;
        quotes: unknown[];
    };
    getOptions(opts: {
        lat?: number;
        lng?: number;
        order_value?: string;
    }): {
        serviceable: boolean;
        options: MockDeliveryOption[];
    };
}

interface ActivityService {
    recordEvents(businessId: string, sessionId: string | undefined, events: {
        event_type: string;
        payload?: Record<string, unknown>;
    }[]): {
        recorded: number;
    };
    getState(businessId: string, sessionId: string | undefined): unknown;
    getRecommendations(businessId: string): unknown;
    dismissMessage(messageId: string): {
        dismissed: boolean;
        message_id: string;
    };
}

interface SupportService {
    openConversation(businessId: string, customerId?: string): MockConversation;
    sendMessage(conversationId: string, body: {
        content: string;
        content_type?: string;
        sender_type?: "customer" | "agent";
    }): MockChatMessage;
    listMessages(conversationId: string, opts?: {
        limit?: number;
    }): MockChatMessage[];
}

interface UploadService {
    init(businessId: string, body: {
        filename: string;
        mime_type: string;
        size_bytes: number;
    }): MockUpload;
    confirm(body: {
        upload_id: string;
    }): MockUpload;
}

interface LiteService {
    bootstrap(businessId: string): unknown;
    getTable(tableId: string): unknown;
    getMenu(businessId: string): unknown;
    getMenuCategory(categoryId: string): unknown;
}

interface MockAddress {
    id: string;
    customer_id: string;
    label: string;
    street_address: string;
    apartment: string | null;
    city: string;
    region: string;
    postal_code: string | null;
    country: string | null;
    delivery_instructions: string | null;
    phone_for_delivery: string | null;
    latitude: number | null;
    longitude: number | null;
    is_default: boolean;
    usage_count: number;
    last_used_at: string | null;
    created_at: string;
    updated_at: string;
}
interface MockMobileMoney {
    id: string;
    customer_id: string;
    phone_number: string;
    provider: string;
    label: string;
    is_verified: boolean;
    verification_date: string | null;
    is_default: boolean;
    usage_count: number;
    last_used_at: string | null;
    success_rate: number;
    created_at: string;
    updated_at: string;
}
interface MockLinkPreferences {
    customer_id: string;
    is_link_enabled: boolean;
    enrolled_at: string | null;
    enrollment_business_id: string | null;
    preferred_order_type: string | null;
    default_address_id: string | null;
    default_mobile_money_id: string | null;
    remember_me: boolean;
    session_duration_days: number;
    two_factor_enabled: boolean;
    notify_on_order: boolean;
    notify_on_payment: boolean;
    created_at: string;
    updated_at: string;
}
interface MockLinkCustomer {
    id: string;
    email: string | null;
    phone: string | null;
    name: string;
    delivery_address: string | null;
    created_at: string;
    updated_at: string;
    metadata: Record<string, unknown> | null;
    account_id: string | null;
}
interface MockLinkSession {
    id: string;
    customer_id: string;
    created_at: string;
    last_used_at: string;
    device_type: "mobile" | "desktop" | "tablet" | "unknown";
    ip_address: string | null;
    user_agent: string | null;
    is_current: boolean;
}
interface CustomerState {
    customer: MockLinkCustomer;
    addresses: Map<string, MockAddress>;
    mobileMoney: Map<string, MockMobileMoney>;
    preferences: MockLinkPreferences;
    sessions: Map<string, MockLinkSession>;
}
interface LinkService {
    /** Get-or-create a customer state record. The mock auth seeds a customer
     *  on first OTP verify; this lazily ensures one exists for tests that
     *  bypass the auth flow. */
    ensureCustomer(customerId: string, seed?: {
        email?: string;
        phone?: string;
        name?: string;
    }): CustomerState;
    getCustomer(customerId: string): MockLinkCustomer;
    getProfile(customerId: string): MockLinkCustomer;
    getLinkData(customerId: string): {
        customer: MockLinkCustomer;
        addresses: MockAddress[];
        mobile_money: MockMobileMoney[];
        preferences: MockLinkPreferences;
        default_address: MockAddress | null;
        default_mobile_money: MockMobileMoney | null;
    };
    isEnrolled(customerId: string): boolean;
    checkStatus(contact: string): boolean;
    enroll(customerId: string, businessId: string, name?: string): MockLinkPreferences;
    getPreferences(customerId: string): MockLinkPreferences;
    updatePreferences(customerId: string, patch: Partial<MockLinkPreferences>): MockLinkPreferences;
    getAddresses(customerId: string): MockAddress[];
    getAddressById(customerId: string, id: string): MockAddress;
    createAddress(customerId: string, input: Partial<MockAddress>): MockAddress;
    updateAddress(customerId: string, id: string, patch: Partial<MockAddress>): MockAddress;
    deleteAddress(customerId: string, id: string): void;
    setDefaultAddress(customerId: string, id: string): void;
    trackAddressUsage(customerId: string, id: string): void;
    getMobileMoney(customerId: string): MockMobileMoney[];
    createMobileMoney(customerId: string, input: Partial<MockMobileMoney>): MockMobileMoney;
    deleteMobileMoney(customerId: string, id: string): void;
    setDefaultMobileMoney(customerId: string, id: string): void;
    trackMobileMoneyUsage(customerId: string, id: string): void;
    verifyMobileMoney(customerId: string, id: string): void;
    getSessions(customerId: string): MockLinkSession[];
    revokeSession(customerId: string, id: string): void;
    revokeAllSessions(customerId: string): number;
}

type SeedName = "default" | "empty" | "reesa-storefront" | "restaurant" | "retail" | "services" | "grocery" | "fashion" | "pharmacy" | "auto";

interface MockOptions {
    seed?: SeedName;
    authMode?: "permissive" | "strict";
    defaultOtp?: string;
    rngSeed?: number;
    frozenAt?: Date;
}
interface ChaosState {
    failNext: {
        route: string;
        count: number;
        status: number;
        code?: string;
    }[];
    latencyByRoute: {
        route: string;
        ms: number;
    }[];
    webhookUrl?: string;
    webhookSecret?: string;
}
interface Deps {
    clock: Clock;
    ids: IdGen;
    bus: MockBus;
    registry: StateRegistry;
    auth: AuthService;
    business: BusinessService;
    catalogue: CatalogueService;
    cart: CartService;
    checkout: CheckoutService;
    orders: OrderService;
    subscriptions: SubscriptionService;
    scheduling: SchedulingService;
    inventory: InventoryService;
    fx: FxService;
    places: PlacesService;
    delivery: DeliveryService;
    activity: ActivityService;
    support: SupportService;
    uploads: UploadService;
    lite: LiteService;
    link: LinkService;
    defaultBusinessId: string;
    chaos: ChaosState;
    resetAll: (seed?: SeedName) => string;
}

interface CreateAppOptions extends MockOptions {
    /**
     * CORS origins to allow. `"*"` (default) allows any origin and is
     * appropriate for local dev. Pass an explicit allow-list for production
     * mock deployments.
     */
    cors?: string[] | "*";
}
interface AppHandle {
    app: Hono;
    deps: Deps;
    request: (path: string, init?: RequestInit) => Promise<Response>;
}

export type { AppHandle as A, CreateAppOptions as C, SeedName as S };
