import type { EventOnlineDetails, EventOnlineDetailsInput } from "./bookingRecords";
import type { SiteVerticalBookingConfig } from "./bookingVerticals";
import type { EventPricingMode, StaffMemberId, UserId } from "@riverbankcms/core";
export type { EventPricingMode } from "@riverbankcms/core";
/**
 * Booking Configuration Contracts
 *
 * These types cover booking pricing, payment terms, event-series configuration,
 * and site-wide booking settings that shape downstream booking flows.
 *
 * Note: Do NOT use these API types as validation schemas. They document wire
 * contracts while the owning services validate and normalize inputs.
 */
export type BookingCollectionOptionKind = "upfront" | "deferred_manual" | "instalment_plan" | "flexible_balance";
export type BookingPaymentArchetype = "event" | "class" | "workshop" | "retreat" | "performance" | "course" | "appointment";
export type BookingPaymentOptionsSource = "default" | "custom";
export type BookingInstalmentIntervalUnit = "day" | "week" | "month";
export type BookingInstalmentPlanConfig = {
    kind: "deposit_plus_one_remainder";
    depositAmountCents: number;
    depositRefundability: BookingDepositRefundPolicy;
    remainderDueCount: number;
    intervalUnit: BookingInstalmentIntervalUnit;
} | {
    kind: "deposit_plus_scheduled_instalments";
    depositAmountCents: number;
    depositRefundability: BookingDepositRefundPolicy;
    instalmentCount: number;
    intervalCount: number;
    intervalUnit: BookingInstalmentIntervalUnit;
} | {
    kind: "equal_scheduled_instalments";
    instalmentCount: number;
    intervalCount: number;
    intervalUnit: BookingInstalmentIntervalUnit;
};
export type BookingDepositRefundPolicy = "refundable" | "non_refundable";
export type BookingFlexibleBalanceDueDateRule = {
    kind: "relative_to_start_date";
    daysBeforeStart: number;
} | {
    kind: "fixed_calendar_date";
    dueAt: string;
};
export type BookingFlexibleBalanceConfig = {
    upfrontAmountCents: number;
    dueDateRule: BookingFlexibleBalanceDueDateRule;
    depositRefundability: BookingDepositRefundPolicy;
};
export type BookingPaymentCollectionOption = {
    kind: "upfront";
} | {
    kind: "deferred_manual";
} | {
    kind: "instalment_plan";
    plan: BookingInstalmentPlanConfig;
} | {
    kind: "flexible_balance";
    config: BookingFlexibleBalanceConfig;
};
export type BookingPaymentTermsConfig = {
    allowedOptions: BookingPaymentCollectionOption[];
};
export type PublicBookingPaymentTermsAvailability = {
    kind: "available";
    paymentTerms: BookingPaymentTermsConfig;
} | {
    kind: "pending_stripe_setup";
    paymentTerms: BookingPaymentTermsConfig;
    reason: "online_payment_configured_before_launch";
};
export type BookingPaymentDefaults = Record<BookingPaymentArchetype, BookingPaymentTermsConfig>;
export type BookingPricingRequirement = "none" | "required";
export type BookingPricingStrategy = "free" | "single" | "tiered";
export type BookingPricingAttendanceScope = "in_person" | "online" | "both";
export type BookingPricingOption = {
    id: string;
    name: string;
    description: string | null;
    priceAmount: number;
    isActive: boolean;
    sortOrder: number;
    capacityLimit: number | null;
    saleStartsAt: string | null;
    saleEndsAt: string | null;
    attendanceScope?: BookingPricingAttendanceScope | null;
};
export type BookingPricingOptionInput = {
    id?: string;
    name: string;
    description?: string | null;
    priceAmount: number;
    isActive?: boolean;
    sortOrder?: number;
    capacityLimit?: number | null;
    saleStartsAt?: string | null;
    saleEndsAt?: string | null;
    attendanceScope?: BookingPricingAttendanceScope | null;
};
export type BookingPricing = {
    bookingRequirement: BookingPricingRequirement;
    pricingStrategy: BookingPricingStrategy;
    currency: string;
    singlePriceAmount: number | null;
    paymentTerms: BookingPaymentTermsConfig;
    options: readonly BookingPricingOption[];
};
export type BookingPricingInput = {
    bookingRequirement?: BookingPricingRequirement;
    pricingStrategy: BookingPricingStrategy;
    currency: string;
    singlePriceAmount?: number | null;
    paymentTerms?: BookingPaymentTermsConfig;
    options?: readonly BookingPricingOptionInput[];
};
export type EventPreset = "event" | "class" | "workshop" | "retreat" | "performance";
export type EventTicketTypeCapacityMode = "limited" | "unlimited";
export type EventDeliveryMode = "in_person" | "online" | "hybrid";
export type EventAttendanceMode = "in_person" | "online";
export type EventTicketTypeAttendanceScope = "in_person" | "online" | "both";
export type EventModeCapacity = {
    kind: "limited";
    capacity: number;
} | {
    kind: "unlimited";
};
export type EventCapacityByAttendanceMode = {
    inPerson: EventModeCapacity;
    online: EventModeCapacity;
};
export type EventTicketTypeRecord = {
    id: string;
    siteId: string;
    eventSeriesId: string;
    name: string;
    description: string | null;
    priceAmount: number;
    isActive: boolean;
    sortOrder: number;
    capacityMode: EventTicketTypeCapacityMode;
    capacityLimit: number | null;
    attendanceScope: EventTicketTypeAttendanceScope;
    saleStartsAt: string | null;
    saleEndsAt: string | null;
    createdAt: string;
    updatedAt: string;
};
export type PublicEventTicketTypeAvailability = {
    kind: "available";
    remainingCapacity: number | null;
} | {
    kind: "unavailable";
    reason: "inactive" | "not_on_sale_yet" | "sale_ended" | "sold_out" | "event_sold_out";
    remainingCapacity: number | null;
};
export type PublicEventTicketTypeRecord = EventTicketTypeRecord & {
    availability: PublicEventTicketTypeAvailability;
};
export type PublicEventEligibilityTicketTypeRecord = Pick<EventTicketTypeRecord, "id" | "name" | "description" | "priceAmount" | "isActive" | "sortOrder" | "capacityMode" | "capacityLimit" | "attendanceScope" | "saleStartsAt" | "saleEndsAt"> & {
    availability: PublicEventTicketTypeAvailability;
};
export type EventTicketTypeInput = {
    id?: string;
    name: string;
    description?: string | null;
    priceAmount: number;
    isActive?: boolean;
    sortOrder?: number;
    capacityMode?: EventTicketTypeCapacityMode;
    capacityLimit?: number | null;
    attendanceScope?: EventTicketTypeAttendanceScope;
    saleStartsAt?: string | null;
    saleEndsAt?: string | null;
};
export type WaitlistMode = "off" | "on";
export type WaitlistOverride = "inherit" | "off" | "on";
export type EventSeriesRecord = {
    id: string;
    siteId: string;
    preset: EventPreset;
    verticalPresetId: string | null;
    pricingMode: EventPricingMode;
    title: string;
    slug: string;
    venueId: string | null;
    eventCategoryId: string | null;
    contentEntryId: string | null;
    capacity: number | null;
    deliveryMode: EventDeliveryMode;
    capacityByAttendanceMode: EventCapacityByAttendanceMode;
    visibility: "public" | "private" | "unlisted";
    status: "active" | "draft" | "archived" | "cancelled" | "completed";
    recurrenceRule: string | null;
    exceptionsJson: string[];
    tags: string[];
    defaultStartTime: string;
    durationMinutes: number;
    formId: string | null;
    priceDisplay: string | null;
    requiresPayment: boolean;
    priceAmount: number | null;
    priceCurrency: string | null;
    acceptsPasses: boolean;
    acceptsMemberships: boolean;
    paymentTerms: BookingPaymentTermsConfig;
    waitlistMode: WaitlistOverride;
    staffMemberIds?: string[];
    ticketTypes?: EventTicketTypeRecord[];
    /** Arbitrary per-series settings persisted to event_series.settings_json. */
    settingsJson: Record<string, unknown>;
    /** Arbitrary per-series presentation config persisted to event_series.presentation_json. */
    presentationJson: Record<string, unknown> | null;
    onlineDetails?: EventOnlineDetails | null;
    createdAt: string;
    updatedAt: string;
};
export type CreateEventSeriesRequest = {
    preset?: EventPreset;
    verticalPresetId?: string | null;
    pricingMode?: EventPricingMode;
    title: string;
    slug?: string;
    startDate?: string;
    defaultStartTime?: string;
    durationMinutes?: number;
    recurrenceRule?: string | null;
    exceptionsJson?: string[];
    venueId?: string | null;
    capacity?: number | null;
    deliveryMode?: EventDeliveryMode;
    capacityByAttendanceMode?: EventCapacityByAttendanceMode;
    visibility?: "public" | "private" | "unlisted";
    eventCategoryId?: string | null;
    status?: "draft" | "active" | "archived" | "cancelled" | "completed";
    /** Arbitrary per-series settings persisted to event_series.settings_json (server-validated). */
    settingsJson?: Record<string, unknown>;
    contentEntryId?: string | null;
    formId?: string | null;
    priceDisplay?: string | null;
    tags?: string[];
    paymentTerms?: BookingPaymentTermsConfig;
    paymentOptionsSource?: BookingPaymentOptionsSource;
    requiresPayment?: boolean;
    priceAmount?: number | null;
    acceptsPasses?: boolean;
    acceptsMemberships?: boolean;
    waitlistMode?: WaitlistOverride;
    staffMemberIds?: string[];
    ticketTypes?: EventTicketTypeInput[];
    onlineDetails?: EventOnlineDetailsInput | null;
    manualDates?: Array<{
        startsAt: string;
        endsAt: string;
    }>;
};
export type UpdateEventSeriesRequest = Partial<Omit<CreateEventSeriesRequest, "status" | "preset">> & {
    status?: "active" | "draft" | "archived" | "cancelled" | "completed";
    migrationTicketTypeId?: string | null;
    migrationTicketTypeIndex?: number | null;
    /**
     * Explicitly cancel future sessions as part of archiving.
     *
     * Archiving does not silently auto-cancel active/future schedules. Set this
     * flag when the caller intends a "cancel and archive" action.
     */
    cancelAndArchive?: boolean;
    /** If true, regenerate future occurrences based on updated schedule */
    regenerateSchedule?: boolean;
};
export type BookingModuleToggles = {
    appointments: boolean;
    events: boolean;
};
export type BookingReminderOverrides = Record<string, number>;
export type EventBookingPolicyMode = "never" | "always" | "cutoff";
export type EventFeedbackDedupMode = "series" | "site";
export type EventFeedbackScopeMode = "all_categories" | "categories" | "event_series";
export type AppointmentFollowUpScopeMode = "all_services" | "selected_services";
export type EventFeedbackScopeIds = {
    eventCategoryIds: string[];
    eventSeriesIds: string[];
};
export type AppointmentFollowUpScopeIds = {
    serviceIds: string[];
};
export type EventFeedbackSettings = {
    enabled: boolean;
    delayHours: number;
    dedupMode: EventFeedbackDedupMode;
    eventsScopeMode: EventFeedbackScopeMode;
    scopeIds: EventFeedbackScopeIds;
    feedbackUrl: string | null;
};
export type AppointmentFollowUpSettings = {
    enabled: boolean;
    delayHours: number;
    servicesScopeMode: AppointmentFollowUpScopeMode;
    scopeIds: AppointmentFollowUpScopeIds;
};
/**
 * Site-wide policy for event booking refunds/transfers.
 *
 * - `mode='cutoff'`: allowed until `cutoffHours` before event start
 * - `mode='always'`: allowed until event start time
 * - `mode='never'`: not allowed for customers
 */
export type EventBookingPolicy = {
    mode: EventBookingPolicyMode;
    cutoffHours: number;
};
export type EventBookingPolicies = {
    refunds: EventBookingPolicy;
    transfers: EventBookingPolicy;
};
export type AppointmentBookingPolicies = {
    refunds: EventBookingPolicy;
};
/**
 * Default image type for events (image-only, no video support).
 */
export type BookingDefaultImage = {
    type: "image";
    assetId?: string;
    storageBucket?: string;
    storagePath?: string;
    alt?: string;
    width?: number;
    height?: number;
};
export type BookingWaitlistSettings = {
    defaultMode: WaitlistMode;
    holdDurationHours: number;
};
export type BookingNotificationUpdateKind = "new_booking" | "cancellation" | "reschedule" | "transfer";
export type BookingNotificationRule = {
    kind: "disabled";
} | {
    kind: "send";
    sendToAssignedStaff: boolean;
    extraEmail: string | null;
    sendToSiteOwnerIfNoStaff: boolean;
};
export type BookingNotificationSettings = {
    defaultRule: BookingNotificationRule;
    overrides: Partial<Record<BookingNotificationUpdateKind, BookingNotificationRule>>;
};
export type AppointmentStaffReminderSettings = {
    kind: "disabled";
} | {
    kind: "daily_digest";
    /** Site-local HH:mm send time. */
    localSendTime: string;
};
export declare const DEFAULT_APPOINTMENT_STAFF_DIGEST_LOCAL_SEND_TIME = "07:00";
export type AppointmentStaffChangeNotificationSettings = {
    kind: "disabled";
} | {
    kind: "send_to_assigned_linked_staff";
};
export type AppointmentStaffNotificationSetupHealth = {
    sendableStaffCount: number;
    unlinkedStaff: Array<{
        staffMemberId: StaffMemberId;
        displayName: string;
    }>;
    linkedUserMissingEmail: Array<{
        staffMemberId: StaffMemberId;
        displayName: string;
        userId: UserId;
    }>;
};
export type PersonRecordMode = "disabled" | "general" | "protected";
export type BookingVerticalConfig = SiteVerticalBookingConfig;
export type TeamMemberProfilePagePolicyMode = "disabled" | "selected" | "all";
export type TeamMemberProfilePageSettings = {
    policy: TeamMemberProfilePagePolicyMode;
};
export type BookingSettings = {
    modules: BookingModuleToggles;
    verticalConfig?: BookingVerticalConfig;
    paymentDefaults: BookingPaymentDefaults;
    /** Site-wide mode for person and encounter records. */
    personRecordMode: PersonRecordMode;
    defaultTimezone: string;
    /** Site-wide currency used for bookings (events/appointments) */
    currency: string;
    defaultVenueId: string | null;
    calendarDisplay: "list" | "calendar";
    /** If enabled, refunds issue site credit rather than cash/Stripe refunds. */
    refundsIssueCredit: boolean;
    remindersEnabled: boolean;
    appointmentReminderHours: number;
    /** How many hours before the appointment start customers can still reschedule online. */
    appointmentRescheduleHours: number;
    /** Minimum minutes before an appointment that customers must book by. Site-wide default for the slot engine. */
    appointmentDefaultMinLeadMinutes: number;
    /** Maximum minutes ahead that customers can book an appointment. Site-wide default for the slot engine. */
    appointmentDefaultMaxBookingNoticeMinutes: number;
    eventReminderHours: number;
    appointmentReminderOverrides: BookingReminderOverrides;
    eventReminderOverrides: BookingReminderOverrides;
    /** How far ahead indefinitely repeating events keep dates available (rolling window). */
    eventScheduleWindowMonths: number;
    icsFeedsEnabled: boolean;
    /** Enable email notifications to organizers when new event registrations occur */
    eventOrganizerNotifications: boolean;
    /** Email address for organizer notifications (defaults to site owner if not set) */
    eventOrganizerEmail: string | null;
    /** Site-wide internal booking update notifications. */
    notificationSettings: BookingNotificationSettings;
    /** Staff-facing appointment reminders, separate from customer appointment reminders. */
    appointmentStaffReminder: AppointmentStaffReminderSettings;
    /** Immediate staff-facing notifications for appointment booking changes. */
    appointmentStaffChangeNotifications: AppointmentStaffChangeNotificationSettings;
    /** Shared waitlist defaults for events and courses. */
    waitlists: BookingWaitlistSettings;
    /** Enable event ticketing by default for new/updated event series (can be overridden per series). */
    eventTicketingDefaultEnabled: boolean;
    /** Require guest details (name, phone) for all attendees, not just the booker */
    collectAllAttendeeDetails: boolean;
    /** Site-wide cancellation/refund/transfer policies for event bookings */
    eventBookingPolicies: EventBookingPolicies;
    /** Site-wide refund policy for appointment bookings */
    appointmentBookingPolicies: AppointmentBookingPolicies;
    /** Default image shown for events that don't have their own image */
    defaultEventImage: BookingDefaultImage | null;
    /** Post-event feedback follow-up email configuration */
    eventFeedback: EventFeedbackSettings;
    /** Post-appointment follow-up email configuration */
    appointmentFollowUp: AppointmentFollowUpSettings;
    /** Controls whether team members receive routed profile pages. */
    teamMemberProfilePages?: TeamMemberProfilePageSettings;
};
export type BookingCurrencyEditState = {
    kind: "editable";
} | {
    kind: "locked";
    reason: "paid_history_exists";
};
export type UpdateBookingSettingsRequest = BookingSettings;
export type BookingSettingsEditorSnapshot = {
    settings: BookingSettings;
    updatedAt: string | null;
    currencyEditState: BookingCurrencyEditState;
    appointmentStaffNotificationSetupHealth: AppointmentStaffNotificationSetupHealth;
};
export type BookingSettingsResponse = BookingSettingsEditorSnapshot;
