export type FinanceInvoice = {
  id: number;
  provider: string;
  status: string;
  currency: string;
  amount_due: number;
  amount_paid: number;
  period_start: string | null;
  period_end: string | null;
  stripe_invoice_id: string | null;
  stripe_checkout_session_id: string | null;
  stripe_subscription_id: string | null;
  revenuecat_event_id?: string | null;
  revenuecat_store?: string | null;
  hosted_invoice_url: string;
  description: string;
  created: string;
  last_modified: string;
};

export type FinancePayment = {
  id: number;
  invoice: number | null;
  provider: string;
  status: string;
  currency: string;
  amount: number;
  stripe_payment_intent_id: string | null;
  stripe_charge_id: string | null;
  revenuecat_transaction_id?: string | null;
  paid_at: string | null;
  failure_message: string;
  created: string;
  last_modified: string;
};

export type PlanFeatures = {
  text_generation: boolean;
  image_generation: boolean;
  rag: boolean;
  all_future_features: boolean;
};

export type SubscriptionPlanInfo = {
  slug: string;
  name: string;
  description: string;
  price_cents: number;
  currency: string;
  interval: string;
  is_public: boolean;
  is_selectable: boolean;
  features: PlanFeatures;
  prompt_quota_per_window: number;
  prompt_window_hours: number;
  monthly_token_quota: number | null;
  sort_order: number;
};

export type SubscriptionUsage = {
  prompts_in_window: number;
  prompt_quota: number | null;
  prompts_remaining: number | null;
  window_hours: number;
  tokens_in_period: number | null;
  tokens_out_period: number | null;
  tokens_total_period: number | null;
  turns_missing_token_usage: number;
  monthly_token_quota: number | null;
  tokens_remaining: number | null;
  period_start: string | null;
  period_end: string | null;
};

export type SubscriptionMe = {
  plan: SubscriptionPlanInfo | null;
  status: string;
  source: string;
  needs_checkout: boolean;
  stripe_subscription_id: string;
  revenuecat_original_transaction_id?: string;
  cancel_at_period_end?: boolean;
  current_period_end?: string | null;
  usage: SubscriptionUsage;
};

export type SubscriptionSource =
  | 'none'
  | 'stripe'
  | 'revenuecat'
  | 'backer'
  | 'admin'
  | string;

export function isStoreSubscription(
  source: string | null | undefined
): boolean {
  return source === 'revenuecat';
}

export function isStripeSubscription(
  source: string | null | undefined
): boolean {
  return source === 'stripe';
}

/** Human label for invoice provider / store (history badge). */
export function invoiceProviderLabel(
  invoice: Pick<FinanceInvoice, 'provider' | 'revenuecat_store'>
): string {
  const provider = (invoice.provider || '').toLowerCase();
  if (provider === 'revenuecat') {
    const store = (invoice.revenuecat_store || '').toUpperCase();
    if (
      store.includes('PLAY') ||
      store === 'GOOGLE' ||
      store === 'GOOGLE_PLAY' ||
      store === 'PLAY_STORE'
    ) {
      return 'Play Store';
    }
    if (
      store.includes('APP_STORE') ||
      store.includes('MAC') ||
      store === 'APPLE' ||
      store === 'APP_STORE'
    ) {
      return 'App Store';
    }
    if (store) return store;
    return 'Store';
  }
  if (provider === 'stripe') return 'Stripe';
  return invoice.provider || '—';
}

/** Complimentary / admin-granted access — no Stripe cancel/change. */
export function isComplimentarySubscription(
  subscription: Pick<SubscriptionMe, 'source' | 'needs_checkout'> | null | undefined,
  hasPortalAccess: boolean
): boolean {
  if (!subscription) return false;
  if (subscription.source === 'backer' || subscription.source === 'admin') return true;
  // Paid Stripe / store entitlements are not complimentary even without portal rows.
  if (
    isStripeSubscription(subscription.source) ||
    isStoreSubscription(subscription.source)
  ) {
    return false;
  }
  return !hasPortalAccess && subscription.needs_checkout === false;
}

/** Higher-priced selectable plans relative to the current plan. */
export function higherSelectablePlans(
  plans: SubscriptionPlanInfo[],
  current: SubscriptionPlanInfo | null | undefined
): SubscriptionPlanInfo[] {
  const selectable = plans.filter((p) => p.is_selectable);
  if (!current) return selectable;
  return selectable.filter(
    (p) =>
      p.slug !== current.slug &&
      (p.price_cents > current.price_cents || p.sort_order > current.sort_order)
  );
}

/** True if the plan (or a subscription's plan) includes RAG document search, or unlocks all future features. */
export function planAllowsRag(
  input: SubscriptionPlanInfo | SubscriptionMe | null | undefined
): boolean {
  if (!input) return false;
  const plan: SubscriptionPlanInfo | null | undefined =
    'features' in input ? input : input.plan;
  if (!plan) return false;
  return Boolean(plan.features?.rag || plan.features?.all_future_features);
}

export function otherSelectablePlans(
  plans: SubscriptionPlanInfo[],
  currentSlug: string | null | undefined
): SubscriptionPlanInfo[] {
  return plans.filter((p) => p.is_selectable && p.slug !== currentSlug);
}

/** Display provider-reported token counts; never invent 0 for missing usage. */
export function formatTokenCount(value: number | null | undefined): string {
  if (value === null || value === undefined) return '—';
  return value.toLocaleString();
}

export function formatMoneyCents(amountCents: number, currency: string): string {
  const code = (currency || 'usd').toUpperCase();
  try {
    return new Intl.NumberFormat(undefined, {
      style: 'currency',
      currency: code,
    }).format(amountCents / 100);
  } catch {
    return `${(amountCents / 100).toFixed(2)} ${code}`;
  }
}

export function formatBillingDate(value: string | null | undefined): string {
  if (!value) return '—';
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return '—';
  return date.toLocaleDateString(undefined, {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
  });
}

export function humanizeStatus(status: string): string {
  if (!status) return 'Unknown';
  return status
    .split('_')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(' ');
}

/** Prefer paid / subscription-backed invoices for the plan summary. */
export function pickPrimaryInvoice(invoices: FinanceInvoice[]): FinanceInvoice | null {
  if (!invoices.length) return null;
  const withSub = invoices.find((inv) => Boolean(inv.stripe_subscription_id));
  if (withSub) return withSub;
  const paid = invoices.find((inv) => inv.status === 'paid');
  if (paid) return paid;
  return invoices[0];
}

/** Stripe customer portal only — ignore RevenueCat / store invoices. */
export function canOpenBillingPortal(invoices: FinanceInvoice[]): boolean {
  return invoices.some(
    (inv) =>
      (inv.provider || 'stripe').toLowerCase() === 'stripe' &&
      (Boolean(inv.stripe_subscription_id) || inv.status === 'paid')
  );
}

export function checkoutReturnUrls(): { success_url: string; cancel_url: string } {
  const origin = window.location.origin;
  return {
    success_url: `${origin}/billing/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${origin}/billing/cancel`,
  };
}
