import { useEffect, useState } from 'preact/hooks'

import { createContext } from 'preact'
import { server } from './api'
import { User } from '../shared/model'

type Metadata = {
    title?: string
}

export const MetadataContext = createContext<Metadata>({})

type CurrentUserHook = (
    onLoaded?: (user: User | null) => void
) => [User | null, () => Promise<void>]

export const useCurrentUser: CurrentUserHook = onLoaded => {
    const [user, setUser] = useState(null)

    const logout = async () => {
        await server.post('/api/logout')
        setUser(null)
    }

    useEffect(() => {
        server.get('/api/current-user').then(user => {
            setUser(user)
            onLoaded?.(user)
        })
    }, [])

    return [user, logout]
}

type ReadResourceFunction = <T>(
    url: string | (() => string),
    initialValue: T
) => [T, () => AbortController]

export const useReadResource: ReadResourceFunction = (url, initialValue) => {
    const [value, setValue] = useState(initialValue)

    function refresh() {
        const controller = new AbortController()
        const realUrl = typeof url === 'function' ? url() : url
        fetch(realUrl, { signal: controller.signal })
            .then(res => {
                if (res.ok) {
                    return res.json()
                } else {
                    return initialValue
                }
            })
            .then(newValue => {
                setValue(newValue)
            })

        return controller
    }

    useEffect(() => {
        const controller = refresh()
        return () => {
            controller.abort()
        }
    }, [])

    return [value, refresh]
}
