/* eslint-disable @typescript-eslint/indent */
import type { LiteralUnion } from 'type-fest';

export type EVMChainType = 'ethereum' | 'base';

export type NFTMintChainType = 'arcblock' | EVMChainType;

export type ChainType = 'arcblock' | 'bitcoin' | 'stripe' | EVMChainType;

export type GroupedBN = { [currencyId: string]: string };
export type GroupedStrList = { [currencyId: string]: string[] };

export type OrderDirection = 'ASC' | 'DESC';
export type OrderItem = [string, OrderDirection];
export type OrderInput = string | string[] | OrderItem[];

export type Pagination<T = any> = T & {
  // offset based
  page?: number;
  pageSize?: number;
  limit?: number;
  // TODO: cursor based
  starting_after?: string;
  ending_before?: string;
  order?: OrderInput; // order by field:ASC|DESC or [field:ASC|DESC, ...] or [[field, direction], ...]
};

export type Searchable<T = any> = Pagination<T> & {
  query: string;
};

export type Paginated<T = any> = {
  count: number;
  list: T[];
};

export type InferFormType<T> = Omit<
  T,
  'id' | 'created_at' | 'created_via' | 'updated_at' | 'active' | 'livemode' | 'metadata'
> & {
  metadata: { key: string; value: string }[];
};

export type PriceRecurring = {
  interval: LiteralUnion<'hour' | 'day' | 'week' | 'month' | 'year', string>;
  interval_count: number;
  aggregate_usage?: LiteralUnion<'sum' | 'last_during_period' | 'max' | 'last_ever', string>;
  usage_type?: LiteralUnion<'licensed' | 'metered', string>;
  meter_id?: string;
};

export type PriceCurrency = {
  currency_id: string;
  unit_amount: string;
  tiers: PriceTier[] | null;
  custom_unit_amount: CustomUnitAmount | null;
};

// 这里为triggerEvents的事件类型
type NotificationActionEvents =
  | 'customer.subscription.started'
  | 'customer.subscription.renewed'
  | 'customer.subscription.renew_failed'
  | 'refund.succeeded'
  | 'subscription.stake.slash.succeeded'
  | 'customer.subscription.trial_will_end'
  | 'customer.subscription.trial_start'
  | 'customer.subscription.upgraded'
  | 'customer.subscription.will_renew'
  | 'customer.subscription.will_canceled'
  | 'customer.subscription.deleted';

export type ServiceAction = {
  type?: LiteralUnion<'notification' | 'custom', string>;
  triggerEvents?: NotificationActionEvents[];
  name?: string;
  color?: LiteralUnion<'primary' | 'secondary' | 'success' | 'error' | 'warning', string>;
  variant?: LiteralUnion<'text' | 'contained' | 'outlined', string>;
  text: { [key: string]: string };
  link: string;
};

export type CustomUnitAmount = {
  maximum: string;
  minimum: string;
  preset: string;
  presets: string[];
};

export type PriceTier = {
  // The flat billing amount for an entire tier, regardless of the number of units in the tier.
  flat_amount?: number;

  // The per unit billing amount for each individual unit for which this tier applies.
  unit_amount?: string;

  // The upper bound of this tier.
  up_to?: number;
};

export type TransformQuantity = {
  divide_by: number;
  round: LiteralUnion<'up' | 'down', string>;
};

export type CustomField = {
  key: string;
  label: string;
  type: LiteralUnion<'text' | 'numeric' | 'dropdown', string>;
  optional: boolean;
  text?: {
    maximum_length: number;
    minimum_length: number;
  };
  numeric?: {
    maximum_length: number;
    minimum_length: number;
  };
  dropdown?: {
    options: { label: string; value: string }[];
  };
};

export type AfterPayment = {
  type: LiteralUnion<'redirect' | 'hosted_confirmation', string>;
  redirect?: {
    url: string;
  };
  hosted_confirmation?: {
    custom_message: string;
  };
};

export type SimpleCustomField = {
  name: string;
  value: string;
};

export type DiscountAmount = {
  amount: string;
  discount?: string;
  promotion_code?: string;
  coupon?: string;
};

export type CustomerAddress = {
  city?: string;
  country?: string;
  line1?: string;
  line2?: string;
  postal_code?: string;
  state?: string;
};

export type CustomerShipping = {
  address: CustomerAddress;
  name: string;
  phone: string;
};

export type CustomerDetail = {
  address?: CustomerAddress;
  email?: string;
  name?: string;
  phone?: string;
  // TODO: following are not supported
  // tax_exempt: any;
  // tax_ids: any
};

export type PaymentError = {
  type: LiteralUnion<'api_error' | 'card_error' | 'idempotency_error' | 'invalid_request_error', string>;
  charge?: string;
  code?: string;
  decline_code?: string;
  doc_url?: string;
  message?: string;
  param?: string;
  payment_settings?: any;
  payment_method_id?: string;
  payment_method_type?: string;
};

export type LineItem = {
  price_id: string;
  quantity: number;
  adjustable_quantity?: {
    enabled: boolean;
    maximum: number;
    minimum: number;
  };
  upsell_price_id?: string;
  cross_sell?: boolean;
  custom_amount?: string;
  subscription_data?: SubscriptionData & {
    service_actions?: ServiceAction[];
    billing_cycle_anchor?: number;
    metadata?: Record<string, any>;
    proration_behavior?: LiteralUnion<'create_prorations' | 'none', string>;
    trial_end?: number;
    trial_settings?: {
      end_behavior: {
        missing_payment_method: LiteralUnion<'cancel' | 'pause' | 'create_invoice', string>;
      };
    };
    days_until_due?: number;
    days_until_cancel?: number;
  };
  // TODO: following are not supported
  // price_data?: any;
  // dynamic_tax_rates?: any;
  // tax_rates?: any;
};

export type InvoiceData = {
  description?: string;
  footer?: string;
  metadata?: Record<string, any>;
  custom_fields?: SimpleCustomField[];
};

// @see https://stripe.com/docs/currencies/conversions
// If presentment currency is different from settlement currency, this is the exchange rate snapshot used.
export type CurrencyConversion = {
  amount_subtotal: string;
  amount_total: string;
  fx_rate: string;
  source_currency: string;
};

export type SubscriptionSchedulePhase = {
  billing_cycle_anchor: LiteralUnion<'phase_start' | 'automatic', string>;
  billing_thresholds?: {
    amount_gte: string;
    reset_billing_cycle_anchor: boolean;
  };
  collection_method: LiteralUnion<'charge_automatically' | 'send_invoice', string>;
  coupon_id?: string;
  currency_id?: string;
  description?: string;
  start_date?: number;
  end_date?: number;
  trial_end?: number;
  invoice_settings?: {
    days_until_due?: number;
  };
  items: {
    price: string;
    quantity?: number;
    billing_thresholds?: {
      usage_gte: number;
    };
    // tax_rates?: string[];
  }[];
  metadata?: Record<string, any>;
  // TODO: following fields not supported
  // application_fee_percent?: number;
  // default_payment_method?: string;
  // default_tax_rates?: string[];
  // on_behalf_of?: string;
  // transfer_data?: any;
};

export type PaymentMethodOptions = {
  arcblock?: {
    payer: string;
    hash?: string;
  };
  ethereum?: {
    payer: string;
    hash?: string;
  };
  base?: {
    payer: string;
    hash?: string;
  };
  stripe?: {
    payer: string;
  };
};

export type PaymentMethodSettings = {
  stripe?: {
    dashboard: string;
    publishable_key: string;
    secret_key: string;
    webhook_signing_secret: string;
  };
  arcblock?: {
    chain_id: string;
    api_host: string;
    explorer_host: string;
  };
  ethereum?: {
    chain_id: string;
    api_host: string;
    explorer_host: string;
    native_symbol: string;
    confirmation: number;
  };
  bitcoin?: {
    chain_id: number;
    api_host: string;
    explorer_host: string;
  };
  base?: {
    chain_id: string;
    api_host: string;
    explorer_host: string;
    native_symbol: string;
    confirmation: number;
  };
  google_play?: {
    package_name: string;
    service_account_json: string; // encrypted JSON string of GCP service account credentials
    pubsub_topic_name: string; // projects/<project>/topics/<topic>
  };
  app_store?: {
    bundle_id: string;
    environment: LiteralUnion<'production' | 'sandbox', string>;
    /** App-Specific Shared Secret — only needed when verifying StoreKit 1 (legacy) receipts via Apple's verifyReceipt endpoint. StoreKit 2 JWS path does not use this. */
    shared_secret?: string; // encrypted
    // App Store Server API credentials — only needed when calling Apple back for state refresh.
    // StoreKit 2 JWS verification (the happy path) does NOT need any of these.
    issuer_id?: string;
    key_id?: string;
    private_key_pem?: string; // encrypted .p8 file contents
  };
};

export type VaultConfig = {
  enabled: boolean;
  deposit_threshold: string; // 存入阈值
  withdraw_threshold: string; // 提取阈值
  buffer_threshold: string; // 差额阈值
};

export type PaymentSettings = {
  payment_method_options: PaymentMethodOptions;
  payment_method_types: string[];
};

export type PaymentDetails = {
  arcblock?: {
    tx_hash: string;
    payer: string;
    type?: LiteralUnion<'slash' | 'transfer' | 'delegate' | 'stake_return' | 'credit', string>;
    receiver?: string;
    delegation_address?: string; // The delegation address at the time of authorization (for migration compatibility)
    staking?: {
      tx_hash: string;
      address: string;
    };
  };
  stripe?: {
    payment_intent_id?: string;
    setup_intent_id?: string;
    subscription_id?: string;
    customer_id?: string;
    refund_id?: string;
    payment_method_id?: string;
  };
  ethereum?: {
    tx_hash: string;
    payer: string;
    block_height: string;
    gas_used: string;
    gas_price: string;
    type?: LiteralUnion<'transfer' | 'approve', string>;
  };
  base?: {
    tx_hash: string;
    payer: string;
    block_height: string;
    gas_used: string;
    gas_price: string;
    type?: LiteralUnion<'transfer' | 'approve', string>;
  };
  bitcoin?: {
    tx_hash: string;
    payer: string;
    block_height: number;
    confirmations: number;
  };
  google_play?: {
    purchase_token: string;
    order_id?: string;
    product_id: string;
    subscription_id?: string;
    expiry_time_millis?: string;
    environment?: LiteralUnion<'production' | 'sandbox', string>;
  };
  app_store?: {
    original_transaction_id: string;
    transaction_id?: string;
    product_id: string;
    web_order_line_item_id?: string;
    environment?: LiteralUnion<'Production' | 'Sandbox', string>;
    expires_at?: number; // unix seconds
  };
};

export type PaymentBeneficiary = {
  address: string;
  share: string;
  name?: string;
  avatar?: string;
  memo?: string;
};

export type DonationSettings = {
  target: string;
  title: string;
  description: string;
  reference: string;
  beneficiaries: PaymentBeneficiary[];
  amount: {
    presets?: string[];
    preset?: string;
    minimum?: string;
    maximum?: string;
    custom?: boolean;
  };
  message?: {
    success?: string;
    summary?: string;
  };
  appearance: {
    button: {
      text: any;
      icon?: any;
      size?: string;
      color?: string;
      variant?: string;
    };
    history: {
      variant: string;
    };
  };
};
export type PaymentIntentData = {
  description?: string;
  statement_descriptor?: string;
  beneficiaries?: PaymentBeneficiary[];
  metadata?: Record<string, any>;
};

export type NftMintSettings = {
  enabled: boolean;
  behavior?: LiteralUnion<'per_customer' | 'per_checkout_session', string>;
  factory?: string; // the factory address determines which chain to mint on
  inputs?: Record<string, string>;
};

export interface NftMintItem {
  tx_hash?: string;
  address: string;
  owner: string;
  error?: string;
}

export type NftMintDetails = {
  type: NFTMintChainType;
  arcblock?: NftMintItem;
  ethereum?: NftMintItem;
  base?: NftMintItem;
};

export type SubscriptionData = {
  description: string;
  trial_period_days: number;
  billing_threshold_amount?: number;
  min_stake_amount?: number;
  metadata?: Record<string, any>;
  recovered_from?: string;
  trial_end?: number;
  trial_currency?: string;
  no_stake?: boolean; // skip stake for this subscription
  notification_settings?: NotificationSetting;
};

export type SubscriptionBillingThresholds = {
  amount_gte: number;
  stake_gte: number;
  reset_billing_cycle_anchor: boolean;
  no_stake?: boolean;
  references_primary_stake?: boolean;
};

// Very similar to PaymentLink
export type PricingTableItem = {
  price_id: string;
  product_id: string;

  adjustable_quantity: {
    enabled: boolean;
    maximum: number;
    minimum: number;
  };

  // The specified behavior after the purchase is complete.
  after_completion?: AfterPayment;

  // Enables user redeemable promotion codes.
  allow_promotion_codes: boolean;

  // Configuration for collecting the customer's billing address.
  billing_address_collection?: LiteralUnion<'auto' | 'required', string>;

  is_highlight: boolean;
  highlight_text?: LiteralUnion<'deal' | 'popular' | 'recommended', string>;

  consent_collection?: {
    promotions?: LiteralUnion<'auto' | 'none', string>;
    terms_of_service?: LiteralUnion<'required' | 'none', string>;
  };

  // Collect additional information from your customer using custom fields. Up to 2 fields are supported.
  custom_fields: CustomField[];

  // Controls phone number collection settings during checkout.
  phone_number_collection?: {
    enabled: boolean;
  };

  // Describes the type of transaction being performed in order to customize relevant text
  submit_type: LiteralUnion<'auto' | 'book' | 'donate' | 'pay', string>;

  // When creating a subscription, the specified configuration data will be used.
  subscription_data?: SubscriptionData;

  nft_mint_settings?: NftMintSettings;

  cross_sell_behavior?: LiteralUnion<'auto' | 'required', string>;

  payment_intent_data?: PaymentIntentData;
};

export type BrandSettings = {
  background_color: string;
  border_style: string;
  button_color: string;
  font_family: string;
};

export type SubscriptionUpdateItem = {
  id?: string;
  deleted?: boolean;
  clear_usage?: boolean;
  price_id?: string;
  quantity?: number;
};

export type EventType = LiteralUnion<
  | 'account.application.authorized'
  | 'account.application.deauthorized'
  | 'account.external_account.created'
  | 'account.external_account.deleted'
  | 'account.external_account.updated'
  | 'account.updated'
  | 'application_fee.created'
  | 'application_fee.refund.updated'
  | 'application_fee.refunded'
  | 'balance.available'
  | 'billing_portal.configuration.created'
  | 'billing_portal.configuration.updated'
  | 'billing_portal.session.created'
  | 'capability.updated'
  | 'cash_balance.funds_available'
  | 'charge.captured'
  | 'charge.dispute.closed'
  | 'charge.dispute.created'
  | 'charge.dispute.funds_reinstated'
  | 'charge.dispute.funds_withdrawn'
  | 'charge.dispute.updated'
  | 'charge.expired'
  | 'charge.failed'
  | 'charge.pending'
  | 'charge.refund.updated'
  | 'charge.refunded'
  | 'charge.succeeded'
  | 'charge.updated'
  | 'checkout.session.async_payment_failed'
  | 'checkout.session.async_payment_succeeded'
  | 'checkout.session.nft_minted'
  | 'checkout.session.completed'
  | 'checkout.session.expired'
  | 'checkout.session.created'
  | 'coupon.created'
  | 'coupon.deleted'
  | 'coupon.updated'
  | 'credit_note.created'
  | 'credit_note.updated'
  | 'credit_note.voided'
  | 'customer_cash_balance_transaction.created'
  | 'customer.created'
  | 'customer.deleted'
  | 'customer.discount.created'
  | 'customer.discount.deleted'
  | 'customer.discount.updated'
  | 'customer.source.created'
  | 'customer.source.deleted'
  | 'customer.source.expiring'
  | 'customer.source.updated'
  | 'customer.subscription.created'
  | 'customer.subscription.deleted'
  | 'customer.subscription.paused'
  | 'customer.subscription.past_due'
  | 'customer.subscription.pending_update_applied'
  | 'customer.subscription.pending_update_expired'
  | 'customer.subscription.resumed'
  | 'customer.subscription.renewed'
  | 'customer.subscription.recovered'
  | 'customer.subscription.upgraded'
  | 'customer.subscription.renew_failed'
  | 'customer.subscription.trial_start'
  | 'customer.subscription.trial_will_end'
  | 'customer.subscription.trial_end'
  | 'customer.subscription.started'
  | 'customer.subscription.updated'
  | 'customer.tax_id.created'
  | 'customer.tax_id.deleted'
  | 'customer.tax_id.updated'
  | 'customer.updated'
  | 'file.created'
  | 'financial_connections.account.created'
  | 'financial_connections.account.deactivated'
  | 'financial_connections.account.disconnected'
  | 'financial_connections.account.reactivated'
  | 'financial_connections.account.refreshed_balance'
  | 'identity.verification_session.canceled'
  | 'identity.verification_session.created'
  | 'identity.verification_session.processing'
  | 'identity.verification_session.redacted'
  | 'identity.verification_session.requires_input'
  | 'identity.verification_session.verified'
  | 'invoice.created'
  | 'invoice.deleted'
  | 'invoice.finalization_failed'
  | 'invoice.finalized'
  | 'invoice.marked_uncollectible'
  | 'invoice.paid'
  | 'invoice.payment_action_required'
  | 'invoice.payment_failed'
  | 'invoice.payment_succeeded'
  | 'invoice.sent'
  | 'invoice.upcoming'
  | 'invoice.updated'
  | 'invoice.voided'
  | 'invoiceitem.created'
  | 'invoiceitem.deleted'
  | 'issuing_authorization.created'
  | 'issuing_authorization.request'
  | 'issuing_authorization.updated'
  | 'issuing_card.created'
  | 'issuing_card.updated'
  | 'issuing_cardholder.created'
  | 'issuing_cardholder.updated'
  | 'issuing_dispute.closed'
  | 'issuing_dispute.created'
  | 'issuing_dispute.funds_reinstated'
  | 'issuing_dispute.submitted'
  | 'issuing_dispute.updated'
  | 'issuing_transaction.created'
  | 'issuing_transaction.updated'
  | 'mandate.updated'
  | 'order.created'
  | 'payment_intent.amount_capturable_updated'
  | 'payment_intent.canceled'
  | 'payment_intent.created'
  | 'payment_intent.partially_funded'
  | 'payment_intent.payment_failed'
  | 'payment_intent.processing'
  | 'payment_intent.requires_action'
  | 'payment_intent.succeeded'
  | 'payment_link.created'
  | 'payment_link.updated'
  | 'payment_method.attached'
  | 'payment_method.automatically_updated'
  | 'payment_method.detached'
  | 'payment_method.updated'
  | 'payout.canceled'
  | 'payout.created'
  | 'payout.failed'
  | 'payout.paid'
  | 'payout.reconciliation_completed'
  | 'payout.updated'
  | 'person.created'
  | 'person.deleted'
  | 'person.updated'
  | 'plan.created'
  | 'plan.deleted'
  | 'plan.updated'
  | 'price.created'
  | 'price.deleted'
  | 'price.updated'
  | 'product.created'
  | 'product.deleted'
  | 'product.updated'
  | 'promotion_code.created'
  | 'promotion_code.updated'
  | 'quote.accepted'
  | 'quote.canceled'
  | 'quote.created'
  | 'quote.finalized'
  | 'radar.early_fraud_warning.created'
  | 'radar.early_fraud_warning.updated'
  | 'recipient.created'
  | 'recipient.deleted'
  | 'recipient.updated'
  | 'refund.created'
  | 'refund.updated'
  | 'refund.succeeded'
  | 'refund.canceled'
  | 'reporting.report_run.failed'
  | 'reporting.report_run.succeeded'
  | 'reporting.report_type.updated'
  | 'review.closed'
  | 'review.opened'
  | 'setup_intent.canceled'
  | 'setup_intent.created'
  | 'setup_intent.requires_action'
  | 'setup_intent.setup_failed'
  | 'setup_intent.succeeded'
  | 'sigma.scheduled_query_run.created'
  | 'sku.created'
  | 'sku.deleted'
  | 'sku.updated'
  | 'source.canceled'
  | 'source.chargeable'
  | 'source.failed'
  | 'source.mandate_notification'
  | 'source.refund_attributes_required'
  | 'source.transaction.created'
  | 'source.transaction.updated'
  | 'subscription_schedule.aborted'
  | 'subscription_schedule.canceled'
  | 'subscription_schedule.completed'
  | 'subscription_schedule.created'
  | 'subscription_schedule.expiring'
  | 'subscription_schedule.released'
  | 'subscription_schedule.updated'
  | 'tax_rate.created'
  | 'tax_rate.updated'
  | 'tax.settings.updated'
  | 'terminal.reader.action_failed'
  | 'terminal.reader.action_succeeded'
  | 'test_helpers.test_clock.advancing'
  | 'test_helpers.test_clock.created'
  | 'test_helpers.test_clock.deleted'
  | 'test_helpers.test_clock.internal_failure'
  | 'test_helpers.test_clock.ready'
  | 'topup.canceled'
  | 'topup.created'
  | 'topup.failed'
  | 'topup.reversed'
  | 'topup.succeeded'
  | 'transfer.created'
  | 'transfer.reversed'
  | 'transfer.updated'
  | 'billing.discrepancy'
  | 'usage.report.empty'
  | 'customer.credit.insufficient'
  | 'customer.credit.low_balance'
  | 'customer.credit_grant.granted'
  | 'customer.credit_grant.depleted'
  | 'exchange_rate.providers_unavailable'
  | 'exchange_rate.spread_exceeded',
  string
>;

export type StripeRefundReason = 'duplicate' | 'fraudulent' | 'requested_by_customer';

export type SettingType = LiteralUnion<'donate' | 'notification', string>;

export type NotificationFrequency = 'default' | 'daily' | 'weekly' | 'monthly';
export type NotificationSchedule = {
  time: string; // HH:mm 格式
  date?: number; // weekly: 0-6, monthly: 1-31
};

export type NotificationSettings = {
  frequency: NotificationFrequency;
  schedule?: NotificationSchedule;
};

export type CustomerPreferences = {
  notification?: NotificationSettings;
  // support more preferences
};

export type NotificationSetting = {
  self_handle: boolean;
  exclude_events?: EventType[];
  include_events?: EventType[];
};

export type CreditGrantApplicabilityConfig = {
  scope: {
    prices?: string[]; // 可选，指定适用的价格ID列表
    price_type?: 'metered'; // 可选，按价格类型适用, 目前只支持metered
  };
};

export type MeterEventStatus =
  | 'pending'
  | 'processing'
  | 'requires_action'
  | 'requires_capture'
  | 'completed'
  | 'canceled';

export type MeterEventPayload = {
  customer_id: string;
  value: string;
  subscription_id?: string;
};

export type RechargeConfig = {
  base_price_id: string;
  payment_link_id?: string;
  checkout_url?: string;
  settings?: {
    min_recharge_amount?: number;
    max_recharge_amount?: number;
  };
};

export type NFTConfig = {
  addresses?: string[];
  tags?: string[];
  trusted_issuers?: string[];
  trusted_parents?: string[];
  min_balance?: number;
};

export type VCConfig = {
  roles?: string[];
  trusted_issuers?: string[];
};

export type VerificationType = 'code' | 'nft' | 'vc' | 'user_restricted';

export type Restrictions = {
  currency_options?: Record<
    string,
    {
      minimum_amount: string;
    }
  >;
  first_time_transaction?: boolean;
  minimum_amount?: string;
  minimum_amount_currency?: string;
};

export type LocalizedText = {
  zh: string;
  en: string;
};

export type SimpleSourceData = Record<string, string>;

export type StructuredSourceDataField = {
  key: string;
  label: string | LocalizedText;
  value: string;
  type?: 'text' | 'image' | 'url';
  url?: string;
  group?: string;
};

export type SourceData = SimpleSourceData | StructuredSourceDataField[];

// Credit Schedule Configuration (embedded in Price.metadata.credit_config)
export type CreditScheduleConfig = {
  enabled: boolean;
  delivery_mode: 'invoice' | 'schedule';
  interval_value: number;
  interval_unit: 'hour' | 'day' | 'week' | 'month';
  amount_per_grant?: string; // Fixed amount per grant; if not set, divide total by period
  first_grant_timing?: 'immediate' | 'after_trial' | 'after_first_payment';
  expire_with_next_grant?: boolean; // Whether to expire previous grant when next grant is issued (refresh style)
  max_grants_per_period?: number; // Protection: max grants per billing period
};

// Credit Config for Price metadata
export type CreditConfig = {
  // Existing fields
  credit_amount: string;
  currency_id: string;
  applicable_prices?: string[];
  valid_duration_value?: number;
  valid_duration_unit?: 'hours' | 'days' | 'weeks' | 'months' | 'years';
  priority?: number;

  // New: schedule configuration
  schedule?: CreditScheduleConfig;
};

// Credit Schedule State per Price (stored in Subscription.credit_schedule_state)
export type CreditSchedulePriceState = {
  enabled: boolean;
  schedule_anchor_at: number; // Anchor point for stable seq calculation
  next_grant_at: number; // Next scheduled grant time (scheduled_at)
  last_grant_seq: number; // Last executed seq (for observation/stats)
  grants_in_current_period: number; // Protection counter
  last_grant_id?: string;
  last_error?: string;
};

// Credit Schedule State map (keyed by priceId)
export type CreditScheduleState = {
  [priceId: string]: CreditSchedulePriceState;
};

// Credit Grant on-chain operation status (combined mint, burn and transfer status)
export type CreditGrantChainStatus =
  | 'mint_pending'
  | 'mint_completed'
  | 'mint_failed'
  | 'burn_pending'
  | 'burn_completed'
  | 'burn_failed'
  | 'transfer_completed' // for expired credits transferred to system wallet
  | 'transfer_failed';

// Credit Grant chain operation details
export type CreditGrantChainDetail = {
  // Mint operation details
  mint?: {
    hash?: string;
    at?: number; // timestamp
    error?: string;
    failed_at?: number;
  };
  // Burn operation details (for expiration)
  burn?: {
    hash?: string;
    at?: number; // timestamp
    amount?: string;
    error?: string;
    failed_at?: number;
  };
  // Expired transfer operation details (for expiration - transfer to system wallet)
  expired_transfer?: {
    hash?: string;
    at?: number; // timestamp
    amount?: string;
    error?: string;
    failed_at?: number;
  };
  // Refund burn operation details
  refund?: {
    id?: string; // refund id
    burn_hash?: string;
    burned_amount?: string;
    system_retained?: string; // amount retained by system (consumed portion)
    burn_error?: string;
  };
  // Voided reason
  voided_reason?: 'refund' | 'expired' | 'manual';
};

/**
 * Quote Status (Final Freeze)
 *
 * - used: Quote created and consumed at Submit
 * - paid: Payment completed successfully
 * - payment_failed: Payment flow failed (does NOT mean Quote is invalid)
 *
 * Legacy statuses (deprecated, for backward compatibility only):
 * - active, expired, cancelled, failed
 *
 * @see Intent: blocklets/core/ai/intent/20260112-dynamic-price.md
 */
/**
 * Final Freeze: Quote only has 3 statuses
 * - used: Quote created at Submit, ready for payment
 * - paid: Payment completed successfully
 * - payment_failed: Payment process failed (Quote still valid for retry)
 */
export type QuoteStatus = 'used' | 'paid' | 'payment_failed';

export interface QuoteMetadata {
  calculation?: {
    token_amount_raw?: string; // Deprecated: use total_base_amount_scaled + rate_scaled instead
    unit_amount_raw?: string; // Deprecated: use quoted_amount_unit instead
    total_base_amount_scaled?: string; // BN: total USD amount scaled by 10^8
    rate_scaled?: string; // BN: exchange rate scaled by 10^8
    quoted_amount_unit?: string; // BN: final quoted amount in smallest token unit
  };
  rounding?: {
    mode?: string;
    token_decimals?: number;
  };
  risk?: {
    anomaly_detected?: boolean;
    deviation_percent?: number;
    degraded?: boolean;
    degraded_reason?: string | null;
  };
  rate?: {
    consensus_method?: string;
    providers?: Array<{
      id?: string;
      name?: string;
      rate?: string;
      timestamp_ms?: number;
      degraded?: boolean;
      degraded_reason?: string;
    }>;
  };
  slippage?: {
    percent?: number;
    max_payable_token?: string;
    min_acceptable_rate?: string;
    derived_at_ms?: number;
  };
  context?: Record<string, any>;
}
