/**
 * Fixed Square Payment Service
 * Handles all Square payment processing with proper error handling and currency support
 */

import { TRPCError } from '@trpc/server';

export type SupportedCurrency = 'USD' | 'EUR' | 'GBP' | 'CAD' | 'AUD' | 'JPY';

interface PaymentLinkRequest {
  userId: string;
  amount: number;
  currency: SupportedCurrency;
  coinPackageId: number;
  gcAmount: number;
  scBonusAmount: number;
  returnUrl: string;
}

interface PaymentLinkResponse {
  paymentLink: string;
  paymentId: string;
  expiresAt: Date;
  currency: SupportedCurrency;
}

interface PaymentConfig {
  apiKey: string;
  environment: 'sandbox' | 'production';
  locationId: string;
}

class SquarePaymentServiceFixed {
  private config: PaymentConfig | null = null;
  private initialized: boolean = false;

  constructor() {
    this.initialize();
  }

  /**
   * Initialize the service with environment variables
   */
  private initialize(): void {
    try {
      const apiKey = process.env.SQUARE_ACCESS_TOKEN;
      const locationId = process.env.SQUARE_LOCATION_ID;
      const environment = process.env.NODE_ENV === 'production' ? 'production' : 'sandbox';

      if (!apiKey || !locationId) {
        console.warn('Square credentials not fully configured');
        return;
      }

      this.config = {
        apiKey,
        environment: environment as 'sandbox' | 'production',
        locationId,
      };

      this.initialized = true;
    } catch (error) {
      console.error('Failed to initialize Square service:', error);
    }
  }

  /**
   * Check if service is properly configured
   */
  isConfigured(): boolean {
    return this.initialized && !!this.config;
  }

  /**
   * Create a payment link for Gold Coin purchase
   */
  async createPaymentLink(request: PaymentLinkRequest): Promise<PaymentLinkResponse> {
    if (!this.isConfigured() || !this.config) {
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Square payment service is not properly configured. Please contact support.',
      });
    }

    try {
      // Validate currency
      const validCurrencies: SupportedCurrency[] = ['USD', 'EUR', 'GBP', 'CAD', 'AUD', 'JPY'];
      if (!validCurrencies.includes(request.currency)) {
        throw new Error(`Unsupported currency: ${request.currency}`);
      }

      // Validate amount
      if (request.amount < 0.01) {
        throw new Error('Amount must be at least 0.01');
      }

      // Create idempotency key to prevent duplicate charges
      const idempotencyKey = `${request.userId}-${request.coinPackageId}-${Date.now()}`;

      // Build payment link request
      const paymentLinkRequest = {
        idempotency_key: idempotencyKey,
        quick_pay: {
          name: `${request.gcAmount.toLocaleString()} Gold Coins + ${request.scBonusAmount.toLocaleString()} Bonus SC`,
          price_money: {
            amount: Math.round(request.amount * 100), // Convert to cents
            currency: request.currency,
          },
        },
        checkout_options: {
          ask_for_shipping_address: false,
          redirect_url: request.returnUrl,
        },
      };

      // Call Square API to create checkout session
      const response = await fetch('https://connect.squareup.com/v2/online-checkout/payment-links', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${this.config.apiKey}`,
          'Content-Type': 'application/json',
          'Square-Version': '2024-04-17',
        },
        body: JSON.stringify(paymentLinkRequest),
      });

      if (!response.ok) {
        const errorData = await response.json();
        console.error('Square API error:', errorData);
        throw new Error(`Square API error: ${errorData.errors?.[0]?.detail || 'Unknown error'}`);
      }

      const data = await response.json();

      if (!data.payment_link?.url) {
        throw new Error('No payment link URL returned from Square');
      }

      return {
        paymentLink: data.payment_link.url,
        paymentId: data.payment_link.id || idempotencyKey,
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours
        currency: request.currency,
      };
    } catch (error) {
      console.error('Square payment link creation error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: `Failed to create payment link: ${error instanceof Error ? error.message : 'Unknown error'}`,
      });
    }
  }

  /**
   * Verify webhook signature
   */
  verifyWebhookSignature(
    eventBody: string,
    signatureHeader: string,
    webhookUrl: string
  ): boolean {
    try {
      if (!this.config) {
        console.warn('Square config not available for webhook verification');
        return false;
      }

      // Reconstruct the request body for signature verification
      const webhookKey = process.env.SQUARE_WEBHOOK_SECRET;
      if (!webhookKey) {
        console.warn('SQUARE_WEBHOOK_SECRET not configured');
        return false;
      }

      // Simple signature verification (in production, use Square's SDK)
      const crypto = require('crypto');
      const payload = webhookUrl + eventBody;
      const hash = crypto.createHmac('sha256', webhookKey).update(payload).digest('base64');

      return hash === signatureHeader;
    } catch (error) {
      console.error('Webhook verification error:', error);
      return false;
    }
  }

  /**
   * Get supported currencies
   */
  getSupportedCurrencies(): SupportedCurrency[] {
    return ['USD', 'EUR', 'GBP', 'CAD', 'AUD', 'JPY'];
  }

  /**
   * Convert amount between currencies (mock implementation)
   */
  async convertCurrency(
    amount: number,
    fromCurrency: SupportedCurrency,
    toCurrency: SupportedCurrency
  ): Promise<number> {
    if (fromCurrency === toCurrency) {
      return amount;
    }

    try {
      // In production, use a real currency conversion API
      const exchangeRates: Record<SupportedCurrency, number> = {
        USD: 1.0,
        EUR: 0.92,
        GBP: 0.79,
        CAD: 1.36,
        AUD: 1.53,
        JPY: 149.5,
      };

      const fromRate = exchangeRates[fromCurrency];
      const toRate = exchangeRates[toCurrency];

      if (!fromRate || !toRate) {
        throw new Error('Invalid currency');
      }

      return (amount / fromRate) * toRate;
    } catch (error) {
      console.error('Currency conversion error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to convert currency',
      });
    }
  }

  /**
   * Get payment details
   */
  async getPaymentDetails(paymentId: string): Promise<any> {
    if (!this.isConfigured() || !this.config) {
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Square service not configured',
      });
    }

    try {
      const response = await fetch(`https://connect.squareup.com/v2/payments/${paymentId}`, {
        method: 'GET',
        headers: {
          'Authorization': `Bearer ${this.config.apiKey}`,
          'Square-Version': '2024-04-17',
        },
      });

      if (!response.ok) {
        throw new Error('Failed to retrieve payment details');
      }

      return await response.json();
    } catch (error) {
      console.error('Error retrieving payment details:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to retrieve payment details',
      });
    }
  }

  /**
   * Refund a payment
   */
  async refundPayment(paymentId: string, amount?: number): Promise<any> {
    if (!this.isConfigured() || !this.config) {
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Square service not configured',
      });
    }

    try {
      const refundRequest: any = {
        idempotency_key: `refund-${paymentId}-${Date.now()}`,
      };

      if (amount) {
        refundRequest.amount_money = {
          amount: Math.round(amount * 100),
          currency: 'USD',
        };
      }

      const response = await fetch(`https://connect.squareup.com/v2/refunds`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${this.config.apiKey}`,
          'Content-Type': 'application/json',
          'Square-Version': '2024-04-17',
        },
        body: JSON.stringify(refundRequest),
      });

      if (!response.ok) {
        throw new Error('Failed to process refund');
      }

      return await response.json();
    } catch (error) {
      console.error('Refund error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to process refund',
      });
    }
  }
}

export const squarePaymentServiceFixed = new SquarePaymentServiceFixed();
