/**
 * Payments API
 * Functions for managing payment configuration (API keys and Connect)
 */

import apiClient from './client';

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

export type PaymentMode = 'direct_api' | 'connect' | 'none';
export type KeyStatus = 'active' | 'invalid' | 'deprecated';
export type AccountStatus = 'pending' | 'onboarding' | 'active' | 'restricted' | 'rejected';

export interface ApiKeysInfo {
  id: number;
  status: KeyStatus;
  secret_key_masked: string;
  publishable_key_masked: string;
  last_validated_at: string | null;
  stripe_account_id: string;
  stripe_account_name: string;
  validation_error: string;
  created_at: string;
  updated_at: string;
}

export interface ConnectAccountInfo {
  id: number;
  business: number;
  business_name: string;
  business_subdomain: string;
  stripe_account_id: string;
  account_type: 'standard' | 'express' | 'custom';
  status: AccountStatus;
  charges_enabled: boolean;
  payouts_enabled: boolean;
  details_submitted: boolean;
  onboarding_complete: boolean;
  onboarding_link: string | null;
  onboarding_link_expires_at: string | null;
  is_onboarding_link_valid: boolean;
  created_at: string;
  updated_at: string;
}

export interface PaymentConfig {
  payment_mode: PaymentMode;
  tier: string;
  can_accept_payments: boolean;
  api_keys: ApiKeysInfo | null;
  connect_account: ConnectAccountInfo | null;
}

export interface ApiKeysValidationResult {
  valid: boolean;
  account_id?: string;
  account_name?: string;
  environment?: string;
  error?: string;
}

export interface ApiKeysCurrentResponse {
  configured: boolean;
  id?: number;
  status?: KeyStatus;
  secret_key_masked?: string;
  publishable_key_masked?: string;
  last_validated_at?: string | null;
  stripe_account_id?: string;
  stripe_account_name?: string;
  validation_error?: string;
  message?: string;
}

export interface ConnectOnboardingResponse {
  account_type: 'standard' | 'custom';
  url: string;
  stripe_account_id?: string;
}

export interface AccountSessionResponse {
  client_secret: string;
  stripe_account_id: string;
  publishable_key: string;
}

// ============================================================================
// Unified Configuration
// ============================================================================

/**
 * Get unified payment configuration status.
 * Returns the complete payment setup for the business.
 */
export const getPaymentConfig = () =>
  apiClient.get<PaymentConfig>('/api/payments/config/status/');

// ============================================================================
// API Keys (Free Tier)
// ============================================================================

/**
 * Get current API key configuration (masked keys).
 */
export const getApiKeys = () =>
  apiClient.get<ApiKeysCurrentResponse>('/api/payments/api-keys/');

/**
 * Save API keys.
 * Validates and stores the provided Stripe API keys.
 */
export const saveApiKeys = (secretKey: string, publishableKey: string) =>
  apiClient.post<ApiKeysInfo>('/api/payments/api-keys/', {
    secret_key: secretKey,
    publishable_key: publishableKey,
  });

/**
 * Validate API keys without saving.
 * Tests the keys against Stripe API.
 */
export const validateApiKeys = (secretKey: string, publishableKey: string) =>
  apiClient.post<ApiKeysValidationResult>('/api/payments/api-keys/validate/', {
    secret_key: secretKey,
    publishable_key: publishableKey,
  });

/**
 * Re-validate stored API keys.
 * Tests stored keys and updates their status.
 */
export const revalidateApiKeys = () =>
  apiClient.post<ApiKeysValidationResult>('/api/payments/api-keys/revalidate/');

/**
 * Delete stored API keys.
 */
export const deleteApiKeys = () =>
  apiClient.delete<{ success: boolean; message: string }>('/api/payments/api-keys/delete/');

// ============================================================================
// Stripe Connect (Paid Tiers)
// ============================================================================

/**
 * Get current Connect account status.
 */
export const getConnectStatus = () =>
  apiClient.get<ConnectAccountInfo>('/api/payments/connect/status/');

/**
 * Initiate Connect account onboarding.
 * Returns a URL to redirect the user for Stripe onboarding.
 */
export const initiateConnectOnboarding = (refreshUrl: string, returnUrl: string) =>
  apiClient.post<ConnectOnboardingResponse>('/api/payments/connect/onboard/', {
    refresh_url: refreshUrl,
    return_url: returnUrl,
  });

/**
 * Refresh Connect onboarding link.
 * For custom Connect accounts that need a new onboarding link.
 */
export const refreshConnectOnboardingLink = (refreshUrl: string, returnUrl: string) =>
  apiClient.post<{ url: string }>('/api/payments/connect/refresh-link/', {
    refresh_url: refreshUrl,
    return_url: returnUrl,
  });

/**
 * Create an Account Session for embedded Connect onboarding.
 * Returns a client_secret for initializing Stripe's embedded Connect components.
 */
export const createAccountSession = () =>
  apiClient.post<AccountSessionResponse>('/api/payments/connect/account-session/');

/**
 * Refresh Connect account status from Stripe.
 * Syncs the local account record with the current state in Stripe.
 */
export const refreshConnectStatus = () =>
  apiClient.post<ConnectAccountInfo>('/api/payments/connect/refresh-status/');

// ============================================================================
// Transaction Analytics
// ============================================================================

export interface Transaction {
  id: number;
  business: number;
  business_name: string;
  stripe_payment_intent_id: string;
  stripe_charge_id: string;
  transaction_type: 'payment' | 'refund' | 'application_fee';
  status: 'pending' | 'succeeded' | 'failed' | 'refunded' | 'partially_refunded';
  amount: number;
  amount_display: string;
  application_fee_amount: number;
  fee_display: string;
  net_amount: number;
  currency: string;
  customer_email: string;
  customer_name: string;
  created_at: string;
  updated_at: string;
  stripe_data?: Record<string, unknown>;
}

export interface TransactionListResponse {
  results: Transaction[];
  count: number;
  page: number;
  page_size: number;
  total_pages: number;
}

export interface TransactionSummary {
  total_transactions: number;
  total_volume: number;
  total_volume_display: string;
  total_fees: number;
  total_fees_display: string;
  net_revenue: number;
  net_revenue_display: string;
  successful_transactions: number;
  failed_transactions: number;
  refunded_transactions: number;
  average_transaction: number;
  average_transaction_display: string;
}

export interface TransactionFilters {
  start_date?: string;
  end_date?: string;
  status?: 'all' | 'succeeded' | 'pending' | 'failed' | 'refunded';
  transaction_type?: 'all' | 'payment' | 'refund' | 'application_fee';
  page?: number;
  page_size?: number;
}

export interface StripeCharge {
  id: string;
  amount: number;
  amount_display: string;
  amount_refunded: number;
  currency: string;
  status: string;
  paid: boolean;
  refunded: boolean;
  description: string | null;
  receipt_email: string | null;
  receipt_url: string | null;
  created: number;
  payment_method_details: Record<string, unknown> | null;
  billing_details: Record<string, unknown> | null;
}

export interface ChargesResponse {
  charges: StripeCharge[];
  has_more: boolean;
}

export interface StripePayout {
  id: string;
  amount: number;
  amount_display: string;
  currency: string;
  status: string;
  arrival_date: number | null;
  created: number;
  description: string | null;
  destination: string | null;
  failure_message: string | null;
  method: string;
  type: string;
}

export interface PayoutsResponse {
  payouts: StripePayout[];
  has_more: boolean;
}

export interface BalanceItem {
  amount: number;
  currency: string;
  amount_display: string;
}

export interface BalanceResponse {
  available: BalanceItem[];
  pending: BalanceItem[];
  available_total: number;
  pending_total: number;
}

export interface ExportRequest {
  format: 'csv' | 'xlsx' | 'pdf' | 'quickbooks';
  start_date?: string;
  end_date?: string;
  include_details?: boolean;
}

/**
 * Get list of transactions with optional filtering.
 */
export const getTransactions = (filters?: TransactionFilters) => {
  const params = new URLSearchParams();
  if (filters?.start_date) params.append('start_date', filters.start_date);
  if (filters?.end_date) params.append('end_date', filters.end_date);
  if (filters?.status && filters.status !== 'all') params.append('status', filters.status);
  if (filters?.transaction_type && filters.transaction_type !== 'all') {
    params.append('transaction_type', filters.transaction_type);
  }
  if (filters?.page) params.append('page', String(filters.page));
  if (filters?.page_size) params.append('page_size', String(filters.page_size));

  const queryString = params.toString();
  return apiClient.get<TransactionListResponse>(
    `/api/payments/transactions/${queryString ? `?${queryString}` : ''}`
  );
};

/**
 * Get a single transaction by ID.
 */
export const getTransaction = (id: number) =>
  apiClient.get<Transaction>(`/api/payments/transactions/${id}/`);

/**
 * Get transaction summary/analytics.
 */
export const getTransactionSummary = (filters?: Pick<TransactionFilters, 'start_date' | 'end_date'>) => {
  const params = new URLSearchParams();
  if (filters?.start_date) params.append('start_date', filters.start_date);
  if (filters?.end_date) params.append('end_date', filters.end_date);

  const queryString = params.toString();
  return apiClient.get<TransactionSummary>(
    `/api/payments/transactions/summary/${queryString ? `?${queryString}` : ''}`
  );
};

/**
 * Get charges from Stripe API.
 */
export const getStripeCharges = (limit: number = 20) =>
  apiClient.get<ChargesResponse>(`/api/payments/transactions/charges/?limit=${limit}`);

/**
 * Get payouts from Stripe API.
 */
export const getStripePayouts = (limit: number = 20) =>
  apiClient.get<PayoutsResponse>(`/api/payments/transactions/payouts/?limit=${limit}`);

/**
 * Get current balance from Stripe API.
 */
export const getStripeBalance = () =>
  apiClient.get<BalanceResponse>('/api/payments/transactions/balance/');

/**
 * Export transaction data.
 * Returns the file data directly for download.
 */
export const exportTransactions = (request: ExportRequest) =>
  apiClient.post('/api/payments/transactions/export/', request, {
    responseType: 'blob',
  });

// ============================================================================
// Transaction Details & Refunds
// ============================================================================

export interface RefundInfo {
  id: string;
  amount: number;
  amount_display: string;
  status: string;
  reason: string | null;
  created: number;
}

export interface PaymentMethodInfo {
  type: string;
  brand?: string;
  last4?: string;
  exp_month?: number;
  exp_year?: number;
  funding?: string;
  bank_name?: string;
}

export interface TransactionDetail extends Transaction {
  refunds: RefundInfo[];
  refundable_amount: number;
  total_refunded: number;
  can_refund: boolean;
  payment_method_info: PaymentMethodInfo | null;
  description: string;
}

export interface RefundRequest {
  amount?: number;
  reason?: 'duplicate' | 'fraudulent' | 'requested_by_customer';
  metadata?: Record<string, string>;
}

export interface RefundResponse {
  success: boolean;
  refund_id: string;
  amount: number;
  amount_display: string;
  status: string;
  reason: string | null;
  transaction_status: string;
}

/**
 * Get detailed transaction information including refund data.
 */
export const getTransactionDetail = (id: number) =>
  apiClient.get<TransactionDetail>(`/api/payments/transactions/${id}/`);

/**
 * Issue a refund for a transaction.
 * @param transactionId - The ID of the transaction to refund
 * @param request - Optional refund request with amount and reason
 */
export const refundTransaction = (transactionId: number, request?: RefundRequest) =>
  apiClient.post<RefundResponse>(`/api/payments/transactions/${transactionId}/refund/`, request || {});
