export interface BillingSubscription {
  id: string;
  restaurantId: string;
  planId: string | null;
  status: string;
  currentPeriodEnd: string | null;
  trialStart: string | null;
  trialEnd: string | null;
  createdAt: string;
  planName: string | null;
  priceMonthly: number;
  priceAnnual: number;
  features: string[];
  limits: Record<string, number>;
  stripeCustomerId: string | null;
  stripeSubscriptionId: string | null;
}

export interface BillingUsage {
  conversations: number;
  branches: number;
  apiCalls: number;
  voiceMinutes: number;
}

export interface Plan {
  id: string;
  name: string;
  priceMonthly: number;
  priceAnnual: number;
  features: string[];
  limits: Record<string, number>;
  isActive: boolean;
  stripePriceIdMonthly: string | null;
  stripePriceIdAnnual: string | null;
}

export interface StripeInvoice {
  id: string;
  number: string | null;
  status: string | null;
  amount: number;
  currency: string;
  periodStart: string;
  periodEnd: string;
  createdAt: string;
  pdfUrl: string | null;
  hostedUrl: string | null;
}

export interface PaymentMethod {
  id: string;
  brand: string;
  last4: string;
  expMonth: number;
  expYear: number;
}

function normalizeSubscription(row: Record<string, unknown>): BillingSubscription {
  return {
    id: row.id as string,
    restaurantId: (row.restaurant_id ?? row.restaurantId) as string,
    planId: (row.plan_id ?? row.planId ?? null) as string | null,
    status: row.status as string,
    currentPeriodEnd: (row.current_period_end ?? row.currentPeriodEnd ?? null) as string | null,
    trialStart: (row.trial_start ?? row.trialStart ?? null) as string | null,
    trialEnd: (row.trial_end ?? row.trialEnd ?? null) as string | null,
    createdAt: (row.created_at ?? row.createdAt) as string,
    planName: (row.plan_name ?? row.planName ?? null) as string | null,
    priceMonthly: Number(row.price_monthly ?? row.priceMonthly ?? 0),
    priceAnnual: Number(row.price_annual ?? row.priceAnnual ?? 0),
    features: (row.features ?? []) as string[],
    limits: (row.limits ?? {}) as Record<string, number>,
    stripeCustomerId: (row.stripe_customer_id ?? row.stripeCustomerId ?? null) as string | null,
    stripeSubscriptionId: (row.stripe_subscription_id ?? row.stripeSubscriptionId ?? null) as string | null,
  };
}

function normalizePlan(row: Record<string, unknown>): Plan {
  return {
    id: row.id as string,
    name: row.name as string,
    priceMonthly: Number(row.price_monthly ?? row.priceMonthly ?? 0),
    priceAnnual: Number(row.price_annual ?? row.priceAnnual ?? 0),
    features: (row.features ?? []) as string[],
    limits: (row.limits ?? {}) as Record<string, number>,
    isActive: (row.is_active ?? row.isActive ?? true) as boolean,
    stripePriceIdMonthly: (row.stripe_price_id_monthly ?? row.stripePriceIdMonthly ?? null) as string | null,
    stripePriceIdAnnual: (row.stripe_price_id_annual ?? row.stripePriceIdAnnual ?? null) as string | null,
  };
}

export async function getSubscription(): Promise<BillingSubscription | null> {
  const res = await fetch('/api/billing');
  if (!res.ok) throw new Error('Failed to fetch subscription');
  const data = await res.json();
  return data.subscription ? normalizeSubscription(data.subscription) : null;
}

export async function getUsage(): Promise<BillingUsage> {
  const res = await fetch('/api/billing/usage');
  if (!res.ok) throw new Error('Failed to fetch usage');
  const data = await res.json();
  return data.usage;
}

export async function listPlans(): Promise<Plan[]> {
  const res = await fetch('/api/billing/plans');
  if (!res.ok) throw new Error('Failed to fetch plans');
  const data = await res.json();
  return (data.plans ?? []).map((p: Record<string, unknown>) => normalizePlan(p));
}

export async function getApiUsageChart(): Promise<{ day: string; calls: number }[]> {
  const res = await fetch('/api/billing/api-usage-chart');
  if (!res.ok) throw new Error('Failed to fetch API usage chart');
  const data = await res.json();
  return data.chart ?? [];
}

export async function startCheckout(planId: string, billingCycle: 'monthly' | 'annual'): Promise<string> {
  const res = await fetch('/api/billing/checkout', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ planId, billingCycle }),
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.error ?? 'Failed to start checkout');
  return (data.url ?? data.redirect) as string;
}

export async function openCustomerPortal(): Promise<string> {
  const res = await fetch('/api/billing/portal', { method: 'POST' });
  const data = await res.json();
  if (!res.ok) throw new Error(data.error ?? 'Failed to open portal');
  return data.url as string;
}

export async function listInvoices(): Promise<StripeInvoice[]> {
  const res = await fetch('/api/billing/invoices');
  if (!res.ok) throw new Error('Failed to fetch invoices');
  const data = await res.json();
  return data.invoices ?? [];
}

export async function getPaymentMethod(): Promise<PaymentMethod | null> {
  const res = await fetch('/api/billing/payment-method');
  if (!res.ok) throw new Error('Failed to fetch payment method');
  const data = await res.json();
  return data.paymentMethod ?? null;
}

export async function createSetupIntent(): Promise<string> {
  const res = await fetch('/api/billing/setup-intent', { method: 'POST' });
  const data = await res.json();
  if (!res.ok) throw new Error(data.error ?? 'Failed to create setup intent');
  return data.clientSecret as string;
}

export async function updatePaymentMethod(paymentMethodId: string): Promise<void> {
  const res = await fetch('/api/billing/setup-intent', {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ paymentMethodId }),
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.error ?? 'Failed to update payment method');
}
