/**
 * Payment Service
 * API client for subscriptions, payments, billing, and wallet
 */

import { apiClient as api } from '../lib/apiClient';
import type {
  PricingPlan,
  Subscription,
  SubscriptionWithPlan,
  Payment,
  PaymentMethod,
  Invoice,
  Wallet,
  WalletTransaction,
  CreateSubscriptionInput,
  CheckoutSession,
  SubscriptionPreview,
  BillingInfo,
  UsageStats,
  ApiResponse,
  SubscriptionResponse,
  WalletResponse,
  PlanInterval,
  Refund,
  RefundEligibility,
  RefundRequest,
} from '../types/payment.types';

// Uses centralized apiClient from lib/apiClient.ts (auto-refresh, multi-tab sync)

// ============================================================================
// Pricing Plans
// ============================================================================

export async function getPlans(): Promise<PricingPlan[]> {
  const response = await api.get<ApiResponse<PricingPlan[]>>('/payments/plans');
  return response.data.data;
}

export async function getPlanBySlug(slug: string): Promise<PricingPlan> {
  const response = await api.get<ApiResponse<PricingPlan>>(`/payments/plans/${slug}`);
  return response.data.data;
}

// Alias for backwards compatibility - backend uses slug for lookup
export async function getPlanById(planId: string): Promise<PricingPlan> {
  return getPlanBySlug(planId);
}

// ============================================================================
// Subscriptions
// ============================================================================

export async function getCurrentSubscription(): Promise<SubscriptionWithPlan | null> {
  try {
    const response = await api.get<ApiResponse<SubscriptionWithPlan>>(
      '/payments/subscription'
    );
    return response.data.data;
  } catch {
    return null;
  }
}

export async function getSubscriptionHistory(): Promise<Subscription[]> {
  const response = await api.get<ApiResponse<Subscription[]>>('/payments/subscription/history');
  return response.data.data;
}

export async function createSubscription(
  input: CreateSubscriptionInput
): Promise<SubscriptionResponse> {
  const response = await api.post<ApiResponse<SubscriptionResponse>>(
    '/payments/subscriptions',
    input
  );
  return response.data.data;
}

export async function cancelSubscription(
  _subscriptionId: string,
  immediately = false
): Promise<Subscription> {
  const response = await api.post<ApiResponse<Subscription>>(
    '/payments/subscription/cancel',
    { immediately }
  );
  return response.data.data;
}

export async function reactivateSubscription(_subscriptionId: string): Promise<Subscription> {
  const response = await api.post<ApiResponse<Subscription>>(
    '/payments/subscription/resume'
  );
  return response.data.data;
}

export async function changeSubscriptionPlan(
  _subscriptionId: string,
  newPlanId: string,
  newInterval: PlanInterval
): Promise<Subscription> {
  const response = await api.post<ApiResponse<Subscription>>(
    '/payments/subscription/change-plan',
    { planId: newPlanId, billingCycle: newInterval === 'year' ? 'yearly' : 'monthly' }
  );
  return response.data.data;
}

export async function previewSubscriptionChange(
  planId: string,
  interval: PlanInterval,
  couponCode?: string
): Promise<SubscriptionPreview> {
  // Note: Backend doesn't have a preview endpoint, so we return a mock for now
  // This would need to be implemented in the backend
  return {
    subtotal: 0,
    discount: 0,
    tax: 0,
    total: 0,
    currency: 'USD',
    interval,
  };
}

// ============================================================================
// Checkout
// ============================================================================

export async function createCheckoutSession(
  planId: string,
  interval: PlanInterval,
  successUrl?: string,
  cancelUrl?: string
): Promise<CheckoutSession> {
  const response = await api.post<ApiResponse<CheckoutSession>>('/payments/checkout', {
    planId,
    billingCycle: interval === 'year' ? 'yearly' : 'monthly',
    successUrl: successUrl || `${window.location.origin}/settings/billing?success=true`,
    cancelUrl: cancelUrl || `${window.location.origin}/pricing?canceled=true`,
  });
  return response.data.data;
}

export async function createPortalSession(returnUrl?: string): Promise<{ url: string }> {
  const response = await api.post<ApiResponse<{ url: string }>>('/payments/billing-portal', {
    returnUrl: returnUrl || `${window.location.origin}/settings/billing`,
  });
  return response.data.data;
}

// ============================================================================
// Payment Methods
// ============================================================================

export async function getPaymentMethods(): Promise<PaymentMethod[]> {
  const response = await api.get<ApiResponse<PaymentMethod[]>>('/payments/methods');
  return response.data.data;
}

export async function addPaymentMethod(paymentMethodId: string): Promise<PaymentMethod> {
  const response = await api.post<ApiResponse<PaymentMethod>>('/payments/methods', {
    paymentMethodId,
  });
  return response.data.data;
}

export async function setDefaultPaymentMethod(paymentMethodId: string): Promise<PaymentMethod> {
  const response = await api.post<ApiResponse<PaymentMethod>>(
    '/payments/methods/default',
    { paymentMethodId }
  );
  return response.data.data;
}

export async function removePaymentMethod(paymentMethodId: string): Promise<void> {
  await api.delete(`/payments/methods/${paymentMethodId}`);
}

// ============================================================================
// Payments & Invoices
// ============================================================================

export async function getPaymentHistory(
  limit = 20,
  offset = 0
): Promise<{ payments: Payment[]; total: number }> {
  const response = await api.get<ApiResponse<{ payments: Payment[]; total: number }>>(
    '/payments/history',
    { params: { limit, offset } }
  );
  return response.data.data;
}

export async function getInvoices(
  limit = 20,
  offset = 0
): Promise<{ invoices: Invoice[]; total: number }> {
  const response = await api.get<ApiResponse<{ invoices: Invoice[]; total: number }>>(
    '/payments/invoices',
    { params: { limit, offset } }
  );
  return response.data.data;
}

export async function getInvoiceById(invoiceId: string): Promise<Invoice> {
  const response = await api.get<ApiResponse<Invoice>>(`/payments/invoices/${invoiceId}`);
  return response.data.data;
}

export async function downloadInvoice(invoiceId: string): Promise<Blob> {
  const response = await api.get(`/payments/invoices/${invoiceId}/pdf`, {
    responseType: 'blob',
  });
  return response.data;
}

// ============================================================================
// Billing Info
// ============================================================================

export async function getBillingInfo(): Promise<BillingInfo | null> {
  try {
    const response = await api.get<ApiResponse<BillingInfo>>('/payments/billing-info');
    return response.data.data;
  } catch {
    return null;
  }
}

export async function updateBillingInfo(info: BillingInfo): Promise<BillingInfo> {
  const response = await api.put<ApiResponse<BillingInfo>>('/payments/billing-info', info);
  return response.data.data;
}

// ============================================================================
// Usage Stats
// ============================================================================

export async function getUsageStats(): Promise<UsageStats> {
  const response = await api.get<ApiResponse<UsageStats>>('/payments/usage');
  return response.data.data;
}

// ============================================================================
// Wallet
// ============================================================================

export async function getWallet(): Promise<WalletResponse> {
  const response = await api.get<ApiResponse<WalletResponse>>('/payments/wallet');
  return response.data.data;
}

export async function getWalletTransactions(
  limit = 20,
  offset = 0,
  type?: string
): Promise<{ transactions: WalletTransaction[]; total: number }> {
  const response = await api.get<
    ApiResponse<{ transactions: WalletTransaction[]; total: number }>
  >('/payments/wallet/transactions', { params: { limit, offset, type } });
  return response.data.data;
}

export async function depositToWallet(
  amount: number,
  paymentMethodId: string
): Promise<{ transaction: WalletTransaction; clientSecret?: string }> {
  const response = await api.post<
    ApiResponse<{ transaction: WalletTransaction; clientSecret?: string }>
  >('/payments/wallet/deposit', { amount, paymentMethodId });
  return response.data.data;
}

export async function withdrawFromWallet(
  amount: number,
  destination: { type: 'bank_account'; accountId: string }
): Promise<WalletTransaction> {
  const response = await api.post<ApiResponse<WalletTransaction>>('/payments/wallet/withdraw', {
    amount,
    destination,
  });
  return response.data.data;
}

// ============================================================================
// Refunds
// ============================================================================

export async function getRefunds(
  limit = 20,
  offset = 0,
  status?: string
): Promise<{ refunds: Refund[]; total: number }> {
  const response = await api.get<ApiResponse<{ refunds: Refund[]; total: number }>>(
    '/payments/refunds',
    { params: { limit, offset, status } }
  );
  return response.data.data;
}

export async function getRefundById(refundId: string): Promise<Refund> {
  const response = await api.get<ApiResponse<Refund>>(`/payments/refunds/${refundId}`);
  return response.data.data;
}

export async function getRefundEligibility(subscriptionId: string): Promise<RefundEligibility> {
  const response = await api.get<ApiResponse<RefundEligibility>>(
    `/payments/refunds/eligibility/${subscriptionId}`
  );
  return response.data.data;
}

export async function requestRefund(request: RefundRequest): Promise<Refund> {
  const response = await api.post<ApiResponse<Refund>>('/payments/refunds', request);
  return response.data.data;
}

export async function cancelRefund(refundId: string): Promise<Refund> {
  const response = await api.delete<ApiResponse<Refund>>(`/payments/refunds/${refundId}`);
  return response.data.data;
}

// ============================================================================
// Coupons
// ============================================================================

export async function validateCoupon(
  code: string,
  planId: string
): Promise<{
  valid: boolean;
  discount: number;
  discountType: 'percent' | 'amount';
  message?: string;
}> {
  const response = await api.post<
    ApiResponse<{
      valid: boolean;
      discount: number;
      discountType: 'percent' | 'amount';
      message?: string;
    }>
  >('/payments/coupons/validate', { code, planId });
  return response.data.data;
}

// ============================================================================
// Summary & Dashboard
// ============================================================================

export async function getBillingSummary(): Promise<{
  subscription: SubscriptionWithPlan | null;
  nextBillingDate: string | null;
  nextBillingAmount: number | null;
  usage: UsageStats;
  recentPayments: Payment[];
  wallet: Wallet | null;
}> {
  const response = await api.get<
    ApiResponse<{
      subscription: SubscriptionWithPlan | null;
      nextBillingDate: string | null;
      nextBillingAmount: number | null;
      usage: UsageStats;
      recentPayments: Payment[];
      wallet: Wallet | null;
    }>
  >('/payments/summary');
  return response.data.data;
}

// Export service object for convenience
export const paymentService = {
  // Plans
  getPlans,
  getPlanById,
  getPlanBySlug,
  // Subscriptions
  getCurrentSubscription,
  getSubscriptionHistory,
  createSubscription,
  cancelSubscription,
  reactivateSubscription,
  changeSubscriptionPlan,
  previewSubscriptionChange,
  // Checkout
  createCheckoutSession,
  createPortalSession,
  // Payment Methods
  getPaymentMethods,
  addPaymentMethod,
  setDefaultPaymentMethod,
  removePaymentMethod,
  // Payments & Invoices
  getPaymentHistory,
  getInvoices,
  getInvoiceById,
  downloadInvoice,
  // Billing Info
  getBillingInfo,
  updateBillingInfo,
  // Usage
  getUsageStats,
  // Wallet
  getWallet,
  getWalletTransactions,
  depositToWallet,
  withdrawFromWallet,
  // Refunds
  getRefunds,
  getRefundById,
  getRefundEligibility,
  requestRefund,
  cancelRefund,
  // Coupons
  validateCoupon,
  // Summary
  getBillingSummary,
};

export default paymentService;
