import type {
  AddFamilyMemberRequest,
  CancelSubscriptionRequest,
  CheckoutSession,
  CheckoutSessionRequest,
  FamilyCapacity,
  FamilyMember,
  MockCompleteRequest,
  Package,
  Subscription,
  SubscriptionCredits,
} from './packages-types';

export class PackagesClientError extends Error {
  constructor(message: string, readonly statusCode: number) {
    super(message);
    this.name = 'PackagesClientError';
  }
}

async function handle<T>(res: Response): Promise<T> {
  if (res.status === 204) return undefined as T;
  const data = (await res.json().catch(() => null)) as
    | T
    | { message: string | string[] }
    | null;
  if (!res.ok) {
    const msg =
      (data as { message?: string | string[] } | null)?.message ??
      `Request failed (${res.status})`;
    throw new PackagesClientError(
      Array.isArray(msg) ? msg.join('\n') : msg,
      res.status,
    );
  }
  return data as T;
}

export const packagesClient = {
  async list(): Promise<Package[]> {
    return handle<Package[]>(
      await fetch('/api/packages', { cache: 'no-store' }),
    );
  },
  async mySubscription(): Promise<Subscription | null> {
    return handle<Subscription | null>(
      await fetch('/api/me/subscription', { cache: 'no-store' }),
    );
  },
  async myCredits(): Promise<SubscriptionCredits> {
    return handle<SubscriptionCredits>(
      await fetch('/api/me/subscription/credits', { cache: 'no-store' }),
    );
  },
  async cancelSubscription(
    payload: CancelSubscriptionRequest = {},
  ): Promise<Subscription> {
    return handle<Subscription>(
      await fetch('/api/me/subscriptions/cancel', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      }),
    );
  },
  async startCheckout(
    payload: CheckoutSessionRequest,
  ): Promise<CheckoutSession> {
    return handle<CheckoutSession>(
      await fetch('/api/checkout/sessions', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      }),
    );
  },
  async completeMockCheckout(
    payload: MockCompleteRequest,
  ): Promise<{ status: string }> {
    return handle<{ status: string }>(
      await fetch('/api/checkout/mock/complete', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      }),
    );
  },

  // ───────── Family-member sharing ─────────
  async listFamilyMembers(): Promise<FamilyMember[]> {
    return handle<FamilyMember[]>(
      await fetch('/api/me/family-members', { cache: 'no-store' }),
    );
  },
  async familyCapacity(): Promise<FamilyCapacity | null> {
    return handle<FamilyCapacity | null>(
      await fetch('/api/me/family-members/capacity', { cache: 'no-store' }),
    );
  },
  async addFamilyMember(payload: AddFamilyMemberRequest): Promise<FamilyMember> {
    return handle<FamilyMember>(
      await fetch('/api/me/family-members', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      }),
    );
  },
  async removeFamilyMember(id: string): Promise<FamilyMember> {
    return handle<FamilyMember>(
      await fetch(`/api/me/family-members/${id}`, { method: 'DELETE' }),
    );
  },
};
