/**
 * Payment Methods Service
 * Handles multiple payment methods including Square, PayPal, Google Pay, Chime, Cash App, Check, and Bitcoin
 */

import { db } from './db.ts';
import { TRPCError } from '@trpc/server';

export type PaymentMethodType = 'square' | 'paypal' | 'google_pay' | 'chime' | 'cash_app' | 'check' | 'bitcoin';

export interface PaymentMethod {
  id: string;
  type: PaymentMethodType;
  name: string;
  description: string;
  isActive: boolean;
  icon: string;
  processingFee: number; // percentage
  minAmount: number;
  maxAmount: number;
}

export interface PaymentTransaction {
  id: string;
  userId: string;
  paymentMethod: PaymentMethodType;
  amount: number;
  currency: string;
  status: 'pending' | 'completed' | 'failed' | 'refunded';
  transactionId: string;
  metadata: Record<string, any>;
  createdAt: Date;
  updatedAt: Date;
}

export interface BitcoinConversion {
  usdAmount: number;
  btcAmount: number;
  exchangeRate: number;
  timestamp: Date;
}

class PaymentMethodsService {
  private paymentMethods: Map<PaymentMethodType, PaymentMethod> = new Map();

  constructor() {
    this.initializePaymentMethods();
  }

  private initializePaymentMethods(): void {
    const methods: PaymentMethod[] = [
      {
        id: 'square',
        type: 'square',
        name: 'Square',
        description: 'Pay with debit or credit card',
        isActive: true,
        icon: '💳',
        processingFee: 2.9, // 2.9% + $0.30
        minAmount: 0.50,
        maxAmount: 10000,
      },
      {
        id: 'paypal',
        type: 'paypal',
        name: 'PayPal',
        description: 'Pay with your PayPal account',
        isActive: true,
        icon: '🅿️',
        processingFee: 3.49, // 3.49% + $0.49
        minAmount: 1.00,
        maxAmount: 10000,
      },
      {
        id: 'google_pay',
        type: 'google_pay',
        name: 'Google Pay',
        description: 'Quick payment with Google Pay',
        isActive: true,
        icon: '🔵',
        processingFee: 2.9,
        minAmount: 0.50,
        maxAmount: 10000,
      },
      {
        id: 'chime',
        type: 'chime',
        name: 'Chime',
        description: 'Pay with your Chime account',
        isActive: true,
        icon: '🟢',
        processingFee: 0, // No fees for Chime transfers
        minAmount: 1.00,
        maxAmount: 5000,
      },
      {
        id: 'cash_app',
        type: 'cash_app',
        name: 'Cash App',
        description: 'Pay with Cash App',
        isActive: true,
        icon: '💵',
        processingFee: 1.5,
        minAmount: 1.00,
        maxAmount: 5000,
      },
      {
        id: 'check',
        type: 'check',
        name: 'Check or Money Order',
        description: 'Mail check or money order',
        isActive: true,
        icon: '✉️',
        processingFee: 0,
        minAmount: 10.00,
        maxAmount: 50000,
      },
      {
        id: 'bitcoin',
        type: 'bitcoin',
        name: 'Bitcoin',
        description: 'Pay with Bitcoin (BTC)',
        isActive: true,
        icon: '₿',
        processingFee: 1.0, // 1% network fee
        minAmount: 0.0001,
        maxAmount: 1.0,
      },
    ];

    methods.forEach((method) => {
      this.paymentMethods.set(method.type, method);
    });
  }

  /**
   * Get all available payment methods
   */
  getAvailableMethods(): PaymentMethod[] {
    return Array.from(this.paymentMethods.values()).filter((m) => m.isActive);
  }

  /**
   * Get specific payment method
   */
  getPaymentMethod(type: PaymentMethodType): PaymentMethod | undefined {
    return this.paymentMethods.get(type);
  }

  /**
   * Process Square payment
   */
  async processSquarePayment(
    userId: string,
    amount: number,
    sourceId: string,
    metadata?: Record<string, any>
  ): Promise<PaymentTransaction> {
    try {
      const squareClient = this.getSquareClient();
      if (!squareClient) {
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Square client not configured',
        });
      }

      // Create payment through Square API
      const { result } = await squareClient.paymentsApi.createPayment({
        sourceId,
        amountMoney: {
          amount: Math.round(amount * 100), // Convert to cents
          currency: 'USD',
        },
        idempotencyKey: `${userId}-${Date.now()}`,
        customerId: await this.getOrCreateSquareCustomer(userId),
      });

      const transaction: PaymentTransaction = {
        id: `txn_${Date.now()}`,
        userId,
        paymentMethod: 'square',
        amount,
        currency: 'USD',
        status: result.payment?.status === 'COMPLETED' ? 'completed' : 'pending',
        transactionId: result.payment?.id || '',
        metadata: {
          squarePaymentId: result.payment?.id,
          ...metadata,
        },
        createdAt: new Date(),
        updatedAt: new Date(),
      };

      await this.saveTransaction(transaction);
      return transaction;
    } catch (error) {
      console.error('Square payment error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to process Square payment',
      });
    }
  }

  /**
   * Process PayPal payment
   */
  async processPayPalPayment(
    userId: string,
    amount: number,
    paypalOrderId: string,
    metadata?: Record<string, any>
  ): Promise<PaymentTransaction> {
    try {
      // Capture PayPal order
      const captureResponse = await fetch(
        `https://api.paypal.com/v2/checkout/orders/${paypalOrderId}/capture`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${process.env.PAYPAL_ACCESS_TOKEN}`,
          },
        }
      );

      if (!captureResponse.ok) {
        throw new Error('PayPal capture failed');
      }

      const captureData = await captureResponse.json();

      const transaction: PaymentTransaction = {
        id: `txn_${Date.now()}`,
        userId,
        paymentMethod: 'paypal',
        amount,
        currency: 'USD',
        status: captureData.status === 'COMPLETED' ? 'completed' : 'pending',
        transactionId: captureData.id,
        metadata: {
          paypalOrderId,
          ...metadata,
        },
        createdAt: new Date(),
        updatedAt: new Date(),
      };

      await this.saveTransaction(transaction);
      return transaction;
    } catch (error) {
      console.error('PayPal payment error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to process PayPal payment',
      });
    }
  }

  /**
   * Process Google Pay payment (through Square)
   */
  async processGooglePayPayment(
    userId: string,
    amount: number,
    sourceId: string,
    metadata?: Record<string, any>
  ): Promise<PaymentTransaction> {
    // Google Pay tokens are processed through Square
    return this.processSquarePayment(userId, amount, sourceId, {
      ...metadata,
      paymentMethod: 'google_pay',
    });
  }

  /**
   * Process Chime payment
   */
  async processChimePayment(
    userId: string,
    amount: number,
    chimeAccountId: string,
    metadata?: Record<string, any>
  ): Promise<PaymentTransaction> {
    try {
      // Chime API integration would go here
      const transaction: PaymentTransaction = {
        id: `txn_${Date.now()}`,
        userId,
        paymentMethod: 'chime',
        amount,
        currency: 'USD',
        status: 'pending', // Requires manual verification
        transactionId: `chime_${Date.now()}`,
        metadata: {
          chimeAccountId,
          ...metadata,
        },
        createdAt: new Date(),
        updatedAt: new Date(),
      };

      await this.saveTransaction(transaction);
      return transaction;
    } catch (error) {
      console.error('Chime payment error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to process Chime payment',
      });
    }
  }

  /**
   * Process Cash App payment
   */
  async processCashAppPayment(
    userId: string,
    amount: number,
    cashAppUserId: string,
    metadata?: Record<string, any>
  ): Promise<PaymentTransaction> {
    try {
      const transaction: PaymentTransaction = {
        id: `txn_${Date.now()}`,
        userId,
        paymentMethod: 'cash_app',
        amount,
        currency: 'USD',
        status: 'pending', // Requires manual verification
        transactionId: `cashapp_${Date.now()}`,
        metadata: {
          cashAppUserId,
          ...metadata,
        },
        createdAt: new Date(),
        updatedAt: new Date(),
      };

      await this.saveTransaction(transaction);
      return transaction;
    } catch (error) {
      console.error('Cash App payment error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to process Cash App payment',
      });
    }
  }

  /**
   * Process check/money order payment
   */
  async processCheckPayment(
    userId: string,
    amount: number,
    checkNumber: string,
    metadata?: Record<string, any>
  ): Promise<PaymentTransaction> {
    try {
      const transaction: PaymentTransaction = {
        id: `txn_${Date.now()}`,
        userId,
        paymentMethod: 'check',
        amount,
        currency: 'USD',
        status: 'pending', // Requires manual verification
        transactionId: `check_${checkNumber}`,
        metadata: {
          checkNumber,
          ...metadata,
        },
        createdAt: new Date(),
        updatedAt: new Date(),
      };

      await this.saveTransaction(transaction);
      return transaction;
    } catch (error) {
      console.error('Check payment error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to process check payment',
      });
    }
  }

  /**
   * Convert USD to Bitcoin
   */
  async convertUSDToBitcoin(usdAmount: number): Promise<BitcoinConversion> {
    try {
      // Fetch current BTC price
      const response = await fetch('https://api.coinbase.com/v2/prices/BTC-USD/spot');
      const data = await response.json();
      const exchangeRate = parseFloat(data.data.amount);

      const btcAmount = usdAmount / exchangeRate;

      return {
        usdAmount,
        btcAmount,
        exchangeRate,
        timestamp: new Date(),
      };
    } catch (error) {
      console.error('Bitcoin conversion error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to convert USD to Bitcoin',
      });
    }
  }

  /**
   * Process Bitcoin payment
   */
  async processBitcoinPayment(
    userId: string,
    usdAmount: number,
    bitcoinAddress: string,
    metadata?: Record<string, any>
  ): Promise<PaymentTransaction> {
    try {
      const conversion = await this.convertUSDToBitcoin(usdAmount);

      const transaction: PaymentTransaction = {
        id: `txn_${Date.now()}`,
        userId,
        paymentMethod: 'bitcoin',
        amount: usdAmount,
        currency: 'USD',
        status: 'pending', // Requires blockchain confirmation
        transactionId: `btc_${Date.now()}`,
        metadata: {
          bitcoinAddress,
          btcAmount: conversion.btcAmount,
          exchangeRate: conversion.exchangeRate,
          ...metadata,
        },
        createdAt: new Date(),
        updatedAt: new Date(),
      };

      await this.saveTransaction(transaction);
      return transaction;
    } catch (error) {
      console.error('Bitcoin payment error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to process Bitcoin payment',
      });
    }
  }

  /**
   * Get or create Square customer
   */
  private async getOrCreateSquareCustomer(userId: string): Promise<string> {
    // Implementation would fetch or create Square customer
    // For now, return a placeholder
    return `square_cust_${userId}`;
  }

  /**
   * Get Square client
   */
  private getSquareClient(): any {
    // Implementation would initialize Square client
    // This is a placeholder
    return null;
  }

  /**
   * Save transaction to database
   */
  private async saveTransaction(transaction: PaymentTransaction): Promise<void> {
    // Implementation would save to database
    console.log('Transaction saved:', transaction);
  }

  /**
   * Get transaction history for user
   */
  async getUserTransactions(userId: string, limit: number = 50): Promise<PaymentTransaction[]> {
    // Implementation would fetch from database
    return [];
  }

  /**
   * Get payment method statistics
   */
  async getPaymentStatistics(): Promise<Record<PaymentMethodType, number>> {
    const stats: Record<PaymentMethodType, number> = {
      square: 0,
      paypal: 0,
      google_pay: 0,
      chime: 0,
      cash_app: 0,
      check: 0,
      bitcoin: 0,
    };

    // Implementation would aggregate from database
    return stats;
  }
}

export const paymentMethodsService = new PaymentMethodsService();
