import { isDefined } from '@rnw-community/shared';

import { type AndroidCardInfo, emptyAndroidCardInfo } from '../../@standard/android/response/android-card-info.js';
import { emptyAndroidIntermediateSigningKey } from '../../@standard/android/response/android-intermediate-signing-key.js';
import { emptyAndroidPaymentMethodToken } from '../../@standard/android/response/android-payment-method-token.js';
import { emptyIosPKToken } from '../../@standard/ios/response/ios-pk-token.js';
import { PaymentsError } from '../../error/payments.error.js';

import { PaymentResponse } from './payment-response.js';

import type { AndroidFullAddress } from '../../@standard/android/response/android-full-address.js';
import type { AndroidMinAddress } from '../../@standard/android/response/android-min-address.js';
import type { AndroidPaymentData } from '../../@standard/android/response/android-payment-data.js';
import type { AndroidPaymentMethodToken } from '../../@standard/android/response/android-payment-method-token.js';
import type { AndroidRawPaymentMethodToken } from '../../@standard/android/response/android-raw-payment-method-token.js';
import type { AndroidSignedKey } from '../../@standard/android/response/android-signed-key.js';
import type { AndroidSignedMessage } from '../../@standard/android/response/android-signed-message.js';
import type { PaymentResponseAddressInterface } from '../../interface/payment-response-address.interface.js';
import type { PaymentResponseDetailsInterface } from '../../interface/payment-response-details.interface.js';
import type { Maybe } from '@rnw-community/shared';

export class AndroidPaymentResponse extends PaymentResponse {
    constructor(requestId: string, methodName: string, jsonData: string, shippingOption: Maybe<string> = null) {
        super(requestId, methodName, AndroidPaymentResponse.parseDetails(jsonData), shippingOption);
    }

    private static parseDetails(jsonData: string): PaymentResponseDetailsInterface {
        try {
            const data = JSON.parse(jsonData) as AndroidPaymentData;

            return {
                billingAddress: AndroidPaymentResponse.parseFullAddress(data.paymentMethodData.info.billingAddress),
                androidPayToken: {
                    ...AndroidPaymentResponse.parseToken(data.paymentMethodData.tokenizationData.token),
                    cardInfo: AndroidPaymentResponse.parseCardInfo(data.paymentMethodData.info),
                },
                applePayToken: emptyIosPKToken,
                payerEmail: data.email,
                ...(isDefined(data.shippingAddress) && {
                    payerName: (data.shippingAddress as AndroidMinAddress).name,
                    payerPhone: (data.shippingAddress as AndroidMinAddress).phoneNumber ?? '',
                }),
                ...(isDefined(data.paymentMethodData.info.billingAddress) && {
                    payerName: (data.paymentMethodData.info.billingAddress as AndroidMinAddress).name,
                    payerPhone: (data.paymentMethodData.info.billingAddress as AndroidMinAddress).phoneNumber ?? '',
                }),
                shippingAddress: AndroidPaymentResponse.parseFullAddress(data.shippingAddress),
            };
        } catch {
            throw new PaymentsError(`Failed parsing PaymentRequest details`);
        }
    }

    private static parseToken(input = '{}'): AndroidPaymentMethodToken {
        if (input === 'examplePaymentMethodToken') {
            return emptyAndroidPaymentMethodToken;
        }

        const parsedToken = JSON.parse(input) as AndroidRawPaymentMethodToken;

        return {
            ...emptyAndroidPaymentMethodToken,
            ...parsedToken,
            rawToken: input,
            intermediateSigningKey: {
                ...(isDefined(parsedToken.intermediateSigningKey)
                    ? {
                          ...parsedToken.intermediateSigningKey,
                          signedKey: JSON.parse(parsedToken.intermediateSigningKey.signedKey) as AndroidSignedKey,
                      }
                    : emptyAndroidIntermediateSigningKey),
            },
            signedMessage: JSON.parse(parsedToken.signedMessage) as AndroidSignedMessage,
        };
    }

    private static parseFullAddress(input?: AndroidFullAddress): PaymentResponseAddressInterface {
        return {
            countryCode: input?.countryCode ?? '',
            postalCode: input?.postalCode ?? '',
            address1: input?.address1 ?? '',
            address2: input?.address2 ?? '',
            address3: input?.address3 ?? '',
            administrativeArea: input?.administrativeArea ?? '',
            locality: input?.locality ?? '',
            sortingCode: input?.sortingCode ?? '',
        };
    }

    private static parseCardInfo(androidCardInfo: AndroidCardInfo): AndroidCardInfo {
        return {
            ...emptyAndroidCardInfo,
            cardNetwork: androidCardInfo.cardNetwork,
            cardDetails: androidCardInfo.cardDetails,
            assuranceDetails: androidCardInfo.assuranceDetails,
        };
    }
}
