const { jwtSecret, jwtValidityDuration } = require("../config")
const { validateCredentials, getCustomerById } = require("../lib/bigcommerceRestAPI")
const { getRefreshToken, createTibiCustomer } = require("../lib/utils")

;(function () {
    function deleteRefreshTokenCookie() {
        context.cookie.set("bkdfRefreshToken", "", {
            maxAge: -1,
            httpOnly: true,
            path: "/api",
        })
    }

    if (context.request().query("logout")) {
        deleteRefreshTokenCookie()
        throw {
            status: 200,
            message: "ok",
            log: false,
        }
    }
    context.data.email = context?.data?.email?.toLowerCase()
    const { email, password } = context.data
    let bigCommerceId

    if (!email || !password) {
        const rT = getRefreshToken()
        console.log(JSON.stringify(rT), "refreshtoken")

        if (rT) {
            /** @type {JWTRefreshClaims} */ // @ts-ignore
            const refreshClaims = rT.claims

            if (!rT.valid) {
                throw {
                    status: 403,
                    error: "token: " + rT.error,
                    log: false,
                }
            }

            bigCommerceId = refreshClaims && refreshClaims.bigCommerceId
            if (!bigCommerceId) {
                deleteRefreshTokenCookie()
                throw {
                    status: 403,
                    error: "token: inavlid claims",
                    log: false,
                }
            }
        } else {
            deleteRefreshTokenCookie()
            throw {
                status: 403,
                error: "missing email and/or password",
                log: false,
            }
        }
    }

    /** @type {Customer[]} */ // @ts-ignore
    let [customer] = context.db.find("bigCommerceCustomer", {
        filter: bigCommerceId
            ? { bigCommerceId }
            : {
                  email,
              },
    })

    if (!customer) {
        if (!bigCommerceId && email) {
            const customerByEmail = getCustomerById(undefined, email, true)
            if (customerByEmail) {
                createTibiCustomer(customerByEmail)
                ;[customer] = context.db.find("bigCommerceCustomer", {
                    filter: bigCommerceId
                        ? { bigCommerceId }
                        : {
                              email,
                          },
                })
            } else {
                deleteRefreshTokenCookie()
                throw {
                    status: 403,
                    error: "login failed",
                    log: false,
                }
            }
        } else {
            deleteRefreshTokenCookie()
            throw {
                status: 403,
                error: "login failed",
                log: false,
            }
        }
    }

    if (!bigCommerceId) {
        // login via username/password
        const validate = validateCredentials(email, password)
        const passwordOK = validate.is_valid
        if (!passwordOK) {
            deleteRefreshTokenCookie()
            throw {
                status: 403,
                error: "login failed",
                log: false,
            }
        }
    }

    if (customer.locked) {
        deleteRefreshTokenCookie()
        throw {
            status: 403,
            error: "customer locked",
            log: false,
        }
    }

    /** @type {JWTLoginClaims} */
    const loginClaims = {
        tibiId: customer.id,
        bigCommerceId: customer.bigCommerceId,
        email: customer.email,
    }

    const token = context.jwt.create(loginClaims, {
        secret: jwtSecret,
        validityDuration: jwtValidityDuration,
    })

    const refreshTokenMaxAge = 60 * 60 * 24 // 24h
    /** @type {JWTRefreshClaims} */
    const refreshClaims = {
        tibiId: customer.id,
        bigCommerceId: customer.bigCommerceId,
        r: 1,
    }
    const nextRefreshToken = context.jwt.create(refreshClaims, {
        secret: jwtSecret,
        validityDuration: refreshTokenMaxAge,
    })

    context.cookie.set("bkdfRefreshToken", nextRefreshToken, {
        maxAge: refreshTokenMaxAge - 60 * 60, // 1h earlier expire
        httpOnly: true,
        path: "/api",
    })

    throw {
        status: 200,
        customer,
        created: new Date(),
        token,
        log: false,
    }
})()
