"use client";

import Script from "next/script";
import {
  createContext,
  useContext,
  useState
} from "react";

type SDKLoadState = "none" | "loading" | "error" | "success";
type SDKForPaymentMethod = "klarna" | "afterpay" | "clearpay" | "applepay";
type SDKName = "klarna" | "afterpay" | "applepay";
interface PaymentSDKState {
  klarna: SDKLoadState;
  afterpay: SDKLoadState;
  applepay: SDKLoadState;
}

interface PaymentContextProps {
  loadSdk: (method:string) => void;
  getSDKState: (method:SDKForPaymentMethod) => SDKLoadState | undefined;
  loadSDKState: PaymentSDKState;
}

const klarnaSDKURL = "https://x.klarnacdn.net/kp/lib/v1/api.js";
const afterpaySDKURL = process.env.NEXT_PUBLIC_APP_ENV === "production" ? "https://portal.afterpay.com/afterpay.js" : "https://portal.sandbox.afterpay.com/afterpay.js";
const applepaySDKURL = "https://applepay.cdn-apple.com/jsapi/1.latest/apple-pay-sdk.js";

const PaymentSDKContext = createContext<PaymentContextProps|null>(null);

const normalizeSDKName = (method:string):SDKName| undefined =>{

    switch(method){

        case "clearpay":
        case "afterpay":
            return "afterpay";

        case "klarna":
            return "klarna";

        case "applepay":
            return "applepay";
        default: 
            return undefined;
    }

}
export function PaymentSDKProvider({
    children
}: {
    children:React.ReactNode;
}){

    const [loadSDKState, setLoadSDKState] = useState<PaymentSDKState>({
        klarna: 'none', // none loading error success
        afterpay: 'none', // none loading error success
        applepay: 'none' // none loading error success
    });

    const loadSdk = (method:string) => {
        const m = normalizeSDKName(method);
        if(m) {
            setLoadSDKState((prev) => {

                if(prev[m] !== "none") {
                    return prev;
                }

                return {
                    ...prev,
                    [m]:"loading"
                };
            });
        }
        
    }
    const onSdkLoad = (m:SDKName) => {
        setLoadSDKState((prev) => {
            return {
                ...prev,
                [m]: 'success'
            }
        });
    };
    const onSdkError = (m:SDKName) => {
        setLoadSDKState((prev) => {
            return {
                ...prev,
                [m]: 'error'
            }
        });
    };
    const getSDKState = (method:SDKForPaymentMethod) => {
        const m = normalizeSDKName(method);
        if(m) {
            return loadSDKState[m];
        } else {
            return undefined;
        }
        
    }

    return (
        <PaymentSDKContext.Provider
            value={{
                loadSdk,
                getSDKState,
                loadSDKState
            }}
        >
            {loadSDKState.klarna !== "none" &&
                <Script id="klarna-sdk" strategy="afterInteractive"
                    src={klarnaSDKURL}
                    onLoad={() => onSdkLoad('klarna')}
                    onError={() => {
                        onSdkError('klarna');
                    }}
                />
            }
            { loadSDKState.afterpay !== "none" &&
                <Script id="afterpay-sdk" strategy="afterInteractive"
                    src={afterpaySDKURL}
                    onLoad={() => onSdkLoad('afterpay')}
                    onError={() => {
                        onSdkError('afterpay');
                    }}
                />
            }
            { loadSDKState.applepay !== "none" &&
                <Script id="applepay-sdk" strategy="afterInteractive"
                    src={applepaySDKURL}
                    onLoad={() => onSdkLoad('applepay')}
                    onError={() => {
                        onSdkError('applepay');
                    }}
                />
            }

            {children}

        </PaymentSDKContext.Provider>
    )

}

export const usePaymentSDKContext = () => {
    const context = useContext(PaymentSDKContext);
    if (!context) {
        throw new Error("usePaymentSDKContext must be used within a PaymentSDKProvider");
    }

    return context;
};