import db from "@/lib/db"
import axios from "axios"


const getTokenFromDb = async () => {
    const bkash_credential = await db.bkashCredentials.findUnique({
        where: {
            id: 1,
        }
    })

    if (bkash_credential) {
        return bkash_credential.token
    }
    else {
        throw new Error("No BKASH credentials found in the database")
    }
}


const getGrantToken = async () => {
    const headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
        "username": process.env.BKASH_USERNAME,
        "password": process.env.BKASH_PASSWORD,
    }

    if (!process.env.BKASH_GRANT_TOKEN_ENDPOINT) {
        throw new Error("BKASH_GRANT_TOKEN_ENDPOINT environment variable is not defined");
    }
    const response = await axios.post(
        process.env.BKASH_GRANT_TOKEN_ENDPOINT,
        {
            "app_key": process.env.BKASH_APP_KEY,
            "app_secret": process.env.BKASH_APP_SECRET,
        },
        {
            headers: headers
        }
    )

    const data = response.data

    const bkash_credential = await db.bkashCredentials.findUnique({
        where: {
            id: 1,
        }
    })

    if (bkash_credential) {
        await db.bkashCredentials.update({
            where: {
                id: 1,
            },
            data: {
                token: data.id_token,
                refresh_token: data.refresh_token,
                expiry_duration: data.expires_in
            }
        })
    }
    else {
        await db.bkashCredentials.create({
            data: {
                token: data.id_token,
                refresh_token: data.refresh_token,
                expiry_duration: data.expires_in
            }
        })
    }



}

const setAuthToken = async () => {

    const bkash_credential = await db.bkashCredentials.findUnique({
        where: {
            id: 1,
        },
    })

    if (bkash_credential) {
        const id_token = bkash_credential.token

        const expiration = bkash_credential.expiry_duration
        const updated_at = bkash_credential.updated_at

        let duration: number | undefined = undefined;
        if (expiration && updated_at) {

            
            duration = Date.now() - (updated_at instanceof Date ? updated_at.getTime() : updated_at)

            duration = duration / 1000

            // console.log(duration)
            // console.log(expiration)
            // console.log(updated_at)

            if (duration <= 0) {
                await getGrantToken()
                return getTokenFromDb()
            }
            else if ((expiration - duration) <= 60){
                await getGrantToken()
                return getTokenFromDb()
            }

            else if ((expiration - duration) <= 600) {

                console.log("REFRESH TOKEN CALLED")
                setRefreshToken(bkash_credential.refresh_token)
                return getTokenFromDb()

            }
            else {
                /// RETURN THE TOKEN
                console.log('TOKEN IS RETURNED')
                return id_token
            }
        }
        else {
            await getGrantToken()
            return getTokenFromDb()
        }

    }
    else {
        await getGrantToken()
        return getTokenFromDb()
    }




}


const setRefreshToken = async (refrsh_token: string) => {
    const headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
        "username": process.env.BKASH_USERNAME,
        "password": process.env.BKASH_PASSWORD,
    }

    if (!process.env.BKASH_REFRESH_TOKEN_ENDPOINT) {
        throw new Error("BKASH_REFRESH_TOKEN_ENDPOINT environment variable is not defined");
    }

    const response = await axios.post(
        process.env.BKASH_REFRESH_TOKEN_ENDPOINT,
        {
            "app_key": process.env.BKASH_APP_KEY,
            "app_secret": process.env.BKASH_APP_SECRET,
            "refresh_token": refrsh_token
        },
        {
            headers: headers
        }
    )

    // console.log(response.data)
    const data = response.data

    await db.bkashCredentials.update({
        where: {
            id: 1,
        },
        data: {
            token: data.id_token,
            refresh_token: data.refresh_token,
            expiry_duration: data.expires_in
        }
    })

    return data.id_token
}

export const createPayment = async (amount: number, phone: string, uuid: string) => {

    // const req = await request.json()

    const token = await setAuthToken()

    const headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
        "Authorization": token,
        "x-app-key": process.env.BKASH_APP_KEY
    }

    const body = {
        "mode": "0011",
        "payerReference": `${phone}`,
        "callbackURL": `${process.env.ROOTURl}/api/payment/bkash`,
        "merchantAssociationInfo": "MI05MID54RF09123456One",
        "amount": `${amount}`,
        "currency": "BDT",
        "intent": "sale",
        "merchantInvoiceNumber": `Invoice${uuid}`
    }

    if (!process.env.BKASH_CREATE_PAYMENT_ENDPOINT) {
        throw new Error("BKASH_CREATE_PAYMENT_ENDPOINT environment variable is not defined");
    }

    const response = await axios.post(process.env.BKASH_CREATE_PAYMENT_ENDPOINT, body, {
        headers: headers
    })

    return response
}


export const executePayment = async (paymentID: string) => {

    const token = await setAuthToken()


    if (!process.env.BKASH_EXECUTE_PAYMENT_ENDPOINT) {
        throw new Error("BKASH_EXECUTE_PAYMENT_ENDPOINT environment variable is not defined");
    }

    const headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
        "Authorization": token,
        "x-app-key": process.env.BKASH_APP_KEY
    }

    const response = await axios.post(process.env.BKASH_EXECUTE_PAYMENT_ENDPOINT, {
        paymentID: paymentID
    } ,{
        headers: headers
    })

    // console.log(response.data)

    return response


}
