import { BlogCard, BlogProps } from ':components/BlogBlocks.tsx'
import Suspense from ':islands/Suspens.tsx'
import { requestApiStream } from ':src/utils.ts'
import { Signal, useSignal } from '@preact/signals'
import type { JSX } from 'preact'
import { useEffect } from 'preact/hooks'

function fillList(
    list: Signal<JSX.Element[]>,
    { limit, ac }: { limit?: number; ac?: AbortController },
) {
    ;(async () => {
        const newsList = requestApiStream<void, BlogProps>(
            'news/fetchAll',
            'GET',
        )

        for await (const news of newsList) {
            list.value = [
                ...list.value,
                BlogCard({ ...news, lastUpdate: new Date(news.lastUpdate) }),
            ]
            if (limit && list.value.length >= limit) break
        }
        ac?.abort()
    })()
}

export default function BlogCardList(
    { limit, usePlaceholder }: { usePlaceholder?: boolean; limit?: number },
) {
    const list = useSignal<JSX.Element[]>([])
    const ac = new AbortController()

    useEffect(() => {
        fillList(list, { limit, ac })
    })

    if (limit && usePlaceholder) {
        const placeholders = Array
            .from({ length: limit })
            .map((_, index) => (
                <Suspense
                    loader={<Placeholder />}
                    fallback={Fallback}
                    signal={ac.signal}
                >
                    {updateFromList(list, index)}
                </Suspense>
            ))
        return <>{placeholders}</>
    }

    return <>{list}</>
}

function Placeholder() {
    return (
        <div class='components__blog_block components__blog_block--card components__blog_block--placeholder'>
            <h3>Chargement ...</h3>
        </div>
    )
}

function Fallback() {
    return (
        <div
            class='components__blog_block components__blog_block--card components__blog_block--fallback'
            inert
        >
            <h3>Pas de news disponible</h3>
        </div>
    )
}

function updateFromList(
    list: Signal<JSX.Element[]>,
    index: number,
): Promise<JSX.Element> {
    const { promise, resolve } = Promise.withResolvers<JSX.Element>()
    list.subscribe((value: JSX.Element[]) => {
        const selected = value.at(index)
        if (selected) {
            resolve(selected)
        }
    })

    return promise
}
