import { CSSProperties, useEffect, useMemo, useState } from 'react'
import Stories from 'react-insta-stories'
import { Story } from 'react-insta-stories/dist/interfaces'

import { BottomNavBar, AnnouncementDetails, Filters } from '../components'
import { useFilters, useStoryDimensions, useStoryIndex } from '../hooks'
import { useAnnouncements } from '../hooks/api'
import { Announcement } from '../api/announcement/types'
import { categoryGraphics } from '../assets/category'
import { UseFetchReturn, gotError } from '../hooks/useFetch'

import puffSpinner from '../assets/puff.svg'

function generateStories(announcements: Announcement[], refresh: () => void): Story[] {
    return announcements.map(announcement => {
        return ({
            id: announcement.id,
            url: announcement.src || categoryGraphics[announcement.category],
            type: announcement.src?.endsWith('mp4') ? 'video' : undefined,
            seeMore: ({ close }: { close: () => void }) => (
                <AnnouncementDetails close={close} refresh={refresh} announcement={announcement} />
            ),
        })
    })
}

function fallbackGenerateStories(announcements: UseFetchReturn<Announcement[]>) {
    if (announcements.loading) {
        return fallbackStory()
    }

    if (gotError(announcements)) {
        return fallbackStory(announcements.error, true)
    }

    if (announcements.data.length === 0) {
        return [{ url: '/static/empty.png' }]
    }

    const stories = generateStories(announcements.data, announcements.refetch)

    return stories
}

const fallbackStory = (text = '', isError = false): Story[] => [{
    content: ({ action }) => {
        // ESLint can't detect that it is a component
        // eslint-disable-next-line react-hooks/rules-of-hooks
        useEffect(() => {
            action('pause')
        }, [action])

        return (
            <div className={`m-auto ${isError ? 'text-danger' : ''}`}>
                {text || <img src={puffSpinner} />}
            </div>
        )
    },
}]

const styles = {
    container: {
        display: 'flex',
        justifyContent: 'center',
        backgroundColor: 'rgb(17, 17, 17)',
    } as CSSProperties,
}

function HomePage() {
    const { height, width } = useStoryDimensions(16 / 9)

    const [filterShown, setFilterShown] = useState(false)

    const [filter, setFilter] = useFilters()

    const announcements = useAnnouncements(filter)

    const stories = useMemo(() => fallbackGenerateStories(announcements), [announcements])

    const index = useStoryIndex(announcements.data?.length)

    return (<>
        <Filters
            filter={filter}
            setFilter={index.withReset(setFilter)}
            filterShown={filterShown}
            setFilterShown={setFilterShown}
        />
        <div style={styles.container}>
            <Stories
                currentIndex={index.n % stories.length}
                onStoryEnd={index.increment}
                onNext={index.increment}
                onPrevious={index.decrement}
                stories={stories}
                defaultInterval={11000}
                height={height}
                width={width}
                loop={true}
                keyboardNavigation={true}
            />
        </div>
        <BottomNavBar
            toggleFilters={setFilterShown}
            width={width}
        />
    </>)
}

export default HomePage
