import jwt_decode, { JwtPayload } from 'jwt-decode'

import { isInt, isObject } from './types'

const TOKEN_KEY = 'Token'

function getToken() {
    const token = localStorage.getItem(TOKEN_KEY)

    if (token === null) {
        return null
    }

    const payload = jwt_decode<JwtPayload>(token)

    // Checks only expiration, not validity
    if (
        payload.exp &&
        (Date.now() >= payload.exp * 1000)
    ) {
        return null
    }

    return token
}

function setToken(token: string) {
    localStorage.setItem(TOKEN_KEY, token)
}

function clearToken() {
    localStorage.removeItem(TOKEN_KEY)
}

type TokenPayload = {
    user_id: number,
}

const isTokenPayload = (data: unknown): data is TokenPayload => isObject(data, {
    'user_id': 'number',
})

function getId() {
    try {
        const token = getToken()

        if (token === null) {
            return -1
        }

        const payload = jwt_decode(token)

        if (!isTokenPayload(payload)) {
            throw new Error('Malformed token payload')
        }

        const id = payload.user_id

        if (!isInt(id) || id < 0) {
            throw new Error(`Not valid id: ${id}`)
        }

        return id
    }
    catch (err) {
        if (import.meta.env.DEV) {
            console.error(err)
        }

        clearToken()

        return -1
    }
}

export { getToken, setToken, clearToken, getId }
