/**
 * Square Payment Service
 * Handles all Square payment processing for Gold Coin Store
 */

import { Client, Environment } from 'square';
import { TRPCError } from '@trpc/server';

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

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

class SquarePaymentService {
  private client: Client;
  private locationId: string;

  constructor() {
    const accessToken = process.env.SQUARE_ACCESS_TOKEN;
    const environment = process.env.NODE_ENV === 'production' ? Environment.Production : Environment.Sandbox;

    if (!accessToken) {
      throw new Error('SQUARE_ACCESS_TOKEN environment variable is required');
    }

    this.client = new Client({
      accessToken,
      environment,
    });

    this.locationId = process.env.SQUARE_LOCATION_ID || '';
  }

  /**
   * Create a payment link for Gold Coin purchase
   */
  async createPaymentLink(request: PaymentLinkRequest): Promise<PaymentLinkResponse> {
    try {
      const { paymentsApi } = this.client;

      // Create checkout session
      const checkoutSession = await paymentsApi.createCheckoutSession({
        idempotencyKey: `${request.userId}-${request.coinPackageId}-${Date.now()}`,
        quickPay: {
          name: `${request.gcAmount} Gold Coins`,
          priceAmount: Math.round(request.amount * 100), // Convert to cents
          currencyCode: 'USD',
        },
        askForShippingAddress: false,
        redirectUrl: request.returnUrl,
        merchantSupportEmail: process.env.OWNER_EMAIL || 'support@coinkrazy.com',
      });

      if (!checkoutSession.checkout?.checkoutPageUrl) {
        throw new Error('Failed to generate checkout page URL');
      }

      return {
        paymentLink: checkoutSession.checkout.checkoutPageUrl,
        paymentId: checkoutSession.checkout.id || '',
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours
      };
    } catch (error) {
      console.error('Square payment link creation error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to create payment link. Please try again.',
        cause: error,
      });
    }
  }

  /**
   * Verify and process payment webhook
   */
  async verifyPaymentWebhook(
    eventBody: any,
    signatureHeader: string,
    webhookUrl: string
  ): Promise<boolean> {
    try {
      const webhookKey = process.env.SQUARE_WEBHOOK_SECRET;
      if (!webhookKey) {
        console.warn('SQUARE_WEBHOOK_SECRET not configured');
        return false;
      }

      // Verify webhook signature
      const isValid = this.client.webhookSubscriptionsApi.verifyWebhookSignature(
        eventBody,
        signatureHeader,
        webhookKey,
        webhookUrl
      );

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

  /**
   * Retrieve payment details
   */
  async getPaymentDetails(paymentId: string): Promise<any> {
    try {
      const { paymentsApi } = this.client;
      const response = await paymentsApi.getPayment(paymentId);
      return response.payment;
    } 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> {
    try {
      const { refundsApi } = this.client;

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

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

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

  /**
   * Create or update customer
   */
  async createOrUpdateCustomer(
    userId: string,
    email: string,
    name: string
  ): Promise<string> {
    try {
      const { customersApi } = this.client;

      // Try to find existing customer
      const searchResponse = await customersApi.searchCustomers({
        query: {
          filter: {
            emailAddress: {
              exact: email,
            },
          },
        },
      });

      if (searchResponse.customers && searchResponse.customers.length > 0) {
        return searchResponse.customers[0].id || '';
      }

      // Create new customer
      const createResponse = await customersApi.createCustomer({
        idempotencyKey: `customer-${userId}-${Date.now()}`,
        givenName: name.split(' ')[0],
        familyName: name.split(' ').slice(1).join(' '),
        emailAddress: email,
        referenceId: userId.toString(),
      });

      return createResponse.customer?.id || '';
    } catch (error) {
      console.error('Customer creation error:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to create or update customer',
      });
    }
  }

  /**
   * Get payment history for customer
   */
  async getCustomerPayments(customerId: string): Promise<any[]> {
    try {
      const { paymentsApi } = this.client;

      const response = await paymentsApi.listPayments({
        customerId,
        limit: 100,
      });

      return response.payments || [];
    } catch (error) {
      console.error('Error retrieving customer payments:', error);
      return [];
    }
  }

  /**
   * Calculate processing fees
   */
  calculateProcessingFee(amount: number): number {
    // Square standard rate: 2.9% + $0.30
    return amount * 0.029 + 0.30;
  }

  /**
   * Validate payment amount
   */
  validatePaymentAmount(amount: number): { valid: boolean; error?: string } {
    if (amount < 0.50) {
      return {
        valid: false,
        error: 'Minimum payment amount is $0.50',
      };
    }

    if (amount > 10000) {
      return {
        valid: false,
        error: 'Maximum payment amount is $10,000',
      };
    }

    return { valid: true };
  }

  /**
   * Get Square location ID
   */
  getLocationId(): string {
    return this.locationId;
  }

  /**
   * Check if Square is properly configured
   */
  isConfigured(): boolean {
    return !!(process.env.SQUARE_ACCESS_TOKEN && process.env.SQUARE_LOCATION_ID);
  }
}

export const squarePaymentService = new SquarePaymentService();
