/**
 * Billing API
 *
 * API client functions for the billing/subscription system.
 */

import apiClient from './client';

// ============================================================================
// Types
// ============================================================================

/**
 * Entitlements - a map of feature codes to their values.
 * Boolean features indicate permission (true/false).
 * Integer features indicate limits.
 */
export interface Entitlements {
  [key: string]: boolean | number | null;
}

/**
 * Plan information (nested in PlanVersion)
 */
export interface Plan {
  code: string;
  name: string;
  description?: string;
}

/**
 * Plan version with pricing and features
 */
export interface PlanVersion {
  id: number;
  name: string;
  is_legacy: boolean;
  is_public?: boolean;
  plan: Plan;
  price_monthly_cents: number;
  price_yearly_cents: number;
  features?: PlanFeature[];
}

/**
 * Feature attached to a plan version
 */
export interface PlanFeature {
  feature_code: string;
  feature_name: string;
  feature_type: 'boolean' | 'integer';
  bool_value?: boolean;
  int_value?: number;
}

/**
 * Current subscription
 */
export interface Subscription {
  id: number;
  status: 'active' | 'canceled' | 'past_due' | 'trialing';
  plan_version: PlanVersion;
  current_period_start: string;
  current_period_end: string;
  canceled_at?: string;
  stripe_subscription_id?: string;
}

/**
 * Add-on product
 */
export interface AddOnProduct {
  id: number;
  code: string;
  name: string;
  description?: string;
  price_monthly_cents: number;
  price_one_time_cents: number;
  stripe_product_id?: string;
  stripe_price_id?: string;
  is_stackable: boolean;
  is_active: boolean;
}

/**
 * Invoice line item
 */
export interface InvoiceLine {
  id: number;
  line_type: 'plan' | 'addon' | 'adjustment' | 'credit';
  description: string;
  quantity: number;
  unit_amount: number;
  total_amount: number;
}

/**
 * Invoice
 */
export interface Invoice {
  id: number;
  status: 'draft' | 'pending' | 'paid' | 'void' | 'uncollectible';
  period_start: string;
  period_end: string;
  subtotal_amount: number;
  total_amount: number;
  plan_name_at_billing: string;
  plan_code_at_billing?: string;
  created_at: string;
  paid_at?: string;
  lines?: InvoiceLine[];
}

// ============================================================================
// API Functions
// ============================================================================

/**
 * Get effective entitlements for the current business.
 * Returns a map of feature codes to their values.
 */
export const getEntitlements = async (): Promise<Entitlements> => {
  try {
    const response = await apiClient.get<Entitlements>('/me/entitlements/');
    return response.data;
  } catch (error) {
    console.error('Failed to fetch entitlements:', error);
    return {};
  }
};

/**
 * Get the current subscription for the business.
 * Returns null if no subscription exists.
 */
export const getCurrentSubscription = async (): Promise<Subscription | null> => {
  try {
    const response = await apiClient.get<Subscription>('/me/subscription/');
    return response.data;
  } catch (error: any) {
    if (error?.response?.status === 404) {
      return null;
    }
    console.error('Failed to fetch subscription:', error);
    throw error;
  }
};

/**
 * Get available plans (public, non-legacy plans).
 */
export const getPlans = async (): Promise<PlanVersion[]> => {
  const response = await apiClient.get<PlanVersion[]>('/billing/plans/');
  return response.data;
};

/**
 * Get available add-on products.
 */
export const getAddOns = async (): Promise<AddOnProduct[]> => {
  const response = await apiClient.get<AddOnProduct[]>('/billing/addons/');
  return response.data;
};

/**
 * Get invoices for the current business.
 */
export const getInvoices = async (): Promise<Invoice[]> => {
  const response = await apiClient.get<Invoice[]>('/billing/invoices/');
  return response.data;
};

/**
 * Get a single invoice by ID.
 * Returns null if not found.
 */
export const getInvoice = async (invoiceId: number): Promise<Invoice | null> => {
  try {
    const response = await apiClient.get<Invoice>(`/billing/invoices/${invoiceId}/`);
    return response.data;
  } catch (error: any) {
    if (error?.response?.status === 404) {
      return null;
    }
    console.error('Failed to fetch invoice:', error);
    throw error;
  }
};
