/home/smartbloks/.trash/extendify/src/Onboarding/pages/CreatingSite.js
import { useEffect, useState, useCallback } from '@wordpress/element'
import { __ } from '@wordpress/i18n'
import { Transition } from '@headlessui/react'
import { colord } from 'colord'
import {
    installPlugin,
    updateTemplatePart,
    addLaunchPagesToNav,
    updateOption,
    getOption,
    getPageById,
    getActivePlugins,
} from '@onboarding/api/WPApi'
import { useConfetti } from '@onboarding/hooks/useConfetti'
import { useWarnOnLeave } from '@onboarding/hooks/useWarnOnLeave'
import { uploadLogo } from '@onboarding/lib/logo'
import { waitFor200Response } from '@onboarding/lib/util'
import {
    createWordpressPages,
    updateGlobalStyleVariant,
} from '@onboarding/lib/wp'
import { useUserSelectionStore } from '@onboarding/state/UserSelections'
import { Logo, Spinner } from '@onboarding/svg'

export const CreatingSite = () => {
    const [isShowing] = useState(true)
    const [confettiReady, setConfettiReady] = useState(false)
    const [confettiColors, setConfettiColors] = useState(['#ffffff'])
    const [warnOnLeaveReady, setWarnOnLeaveReady] = useState(true)
    const canLaunch = useUserSelectionStore((state) => state.canLaunch())
    const { siteType, pages, style, plugins, goals } = useUserSelectionStore()
    const [info, setInfo] = useState([])
    const [infoDesc, setInfoDesc] = useState([])
    const inform = (msg) => setInfo((info) => [msg, ...info])
    const informDesc = (msg) => setInfoDesc((infoDesc) => [msg, ...infoDesc])

    useWarnOnLeave(warnOnLeaveReady)

    const doEverything = useCallback(async () => {
        if (!canLaunch) {
            throw new Error(__('Site is not ready to launch.', 'extendify'))
        }
        try {
            if (!document.body.classList.contains('folded')) {
                window.jQuery('#collapse-button').trigger('click.collapse-menu')
            }

            inform(__('Applying site styles', 'extendify'))
            informDesc(__('A beautiful site in... 3, 2, 1', 'extendify'))
            await new Promise((resolve) => setTimeout(resolve, 1000))

            await waitFor200Response()
            await updateGlobalStyleVariant(style?.variation ?? {})

            await waitFor200Response()
            await updateTemplatePart('extendable/header', style?.headerCode)

            await waitFor200Response()
            await updateTemplatePart('extendable/footer', style?.footerCode)

            if (plugins?.length) {
                inform(__('Installing suggested plugins', 'extendify'))
                for (const [index, plugin] of plugins.entries()) {
                    // TODO: instead of updating here, we could have a progress component
                    // that we can update a % of the width every index/n
                    informDesc(
                        __(
                            `${index + 1}/${plugins.length}: ${plugin.name}`,
                            'extendify',
                        ),
                    )
                    await waitFor200Response()
                    try {
                        await installPlugin(plugin)
                    } catch (e) {
                        // If this fails, wait and try again
                        await waitFor200Response()
                        await installPlugin(plugin)
                    }
                }
            }

            let pageIds, navPages
            inform(__('Generating page content', 'extendify'))
            informDesc(__('Starting off with a full site...', 'extendify'))
            await new Promise((resolve) => setTimeout(resolve, 1000))
            await waitFor200Response()

            const blogPage = {
                // slug is only used internally
                slug: 'blog',
                title: __('Blog', 'extendify'),
            }
            const pagesWithBlog = [...pages, blogPage]
            await waitFor200Response()
            pageIds = await createWordpressPages(pagesWithBlog, siteType, style)
            await waitFor200Response()
            const addBlogPageToNav = goals.some((goal) => goal.slug === 'blog')

            navPages = [...pages]

            navPages = addBlogPageToNav
                ? [...navPages, blogPage]
                : [...navPages]

            // Fetch active plugins after installing plugins
            let { data: activePlugins } = await getActivePlugins()
            if (!Array.isArray(activePlugins)) {
                // Sometimes, seemingly randomly, an object is returned instead of an array
                // if not an object (or array - checked above), then set to undefined
                activePlugins =
                    typeof activePlugins === 'object'
                        ? Object.keys(activePlugins)
                        : undefined
            }
            // Add plugin related pages only if plugin is active
            if (
                activePlugins?.filter((p) => p.includes('woocommerce'))?.length
            ) {
                const shopPageId = await getOption('woocommerce_shop_page_id')
                const shopPage = await getPageById(shopPageId)
                const cartPageId = await getOption('woocommerce_cart_page_id')
                const cartPage = await getPageById(cartPageId)
                if (shopPageId && shopPage && cartPageId && cartPage) {
                    const wooShopPage = {
                        id: shopPageId,
                        slug: shopPage.slug,
                        title: shopPage.title.rendered,
                    }
                    const wooCartPage = {
                        id: cartPageId,
                        slug: cartPage.slug,
                        title: cartPage.title.rendered,
                    }
                    navPages = [...navPages, wooShopPage, wooCartPage]
                }
            }

            if (
                activePlugins?.filter((p) => p.includes('the-events-calendar'))
                    ?.length
            ) {
                const eventsPage = {
                    slug: 'events',
                    title: __('Events', 'extendify'),
                }
                navPages = [...navPages, eventsPage]
            }

            // Upload Logo
            await uploadLogo(
                'https://assets.extendify.com/demo-content/logos/extendify-demo-logo.png',
            )
            await waitFor200Response()

            const updatedHeaderCode = addLaunchPagesToNav(
                navPages,
                pageIds,
                style?.headerCode,
            )

            await waitFor200Response()
            await updateTemplatePart('extendable/header', updatedHeaderCode)

            inform(__('Setting up your site assistant', 'extendify'))
            informDesc(__('Helping your site to be successful...', 'extendify'))
            await new Promise((resolve) => setTimeout(resolve, 1000))
            await waitFor200Response()
            await waitFor200Response()
            await updateOption('permalink_structure', '/%postname%/')
            inform(__('Your site has been created!', 'extendify'))
            informDesc(__('Redirecting in 3, 2, 1...', 'extendify'))
            // fire confetti here
            setConfettiReady(true)
            setWarnOnLeaveReady(false)
            await new Promise((resolve) => setTimeout(resolve, 2500))

            await waitFor200Response()
            await updateOption(
                'extendify_onboarding_completed',
                new Date().toISOString(),
            )

            return pageIds
        } catch (e) {
            console.error(e)
            // if the error is 4xx, we should stop trying and prompt them to reload
            if (e.status >= 400 && e.status < 500) {
                setWarnOnLeaveReady(false)
                const alertMsg = __(
                    'We encountered a server error we cannot recover from. Please reload the page and try again.',
                    'extendify',
                )
                alert(alertMsg)
                location.href = window.extOnbData.adminUrl
            }
            await new Promise((resolve) => setTimeout(resolve, 2000))
            return doEverything()
        }
    }, [goals, pages, plugins, siteType, style, canLaunch])

    useEffect(() => {
        doEverything().then(() => {
            window.location.replace(
                window.extOnbData.adminUrl +
                    'admin.php?page=extendify-assist&extendify-launch-success',
            )
        })
    }, [doEverything])

    useEffect(() => {
        const documentStyles = window.getComputedStyle(document.documentElement)
        const partnerBg = documentStyles?.getPropertyValue(
            '--ext-partner-theme-primary-bg',
        )
        const partnerText = documentStyles?.getPropertyValue(
            '--ext-partner-theme-primary-text',
        )
        if (partnerBg) {
            setConfettiColors([
                colord(partnerBg).darken(0.3).toHex(),
                colord(partnerText).alpha(0.5).toHex(),
                colord(partnerBg).lighten(0.2).toHex(),
            ])
        }
    }, [])

    useConfetti(
        {
            particleCount: 3,
            angle: 320,
            spread: 220,
            origin: { x: 0, y: 0 },
            colors: confettiColors,
        },
        2500,
        confettiReady,
    )

    return (
        <Transition
            show={isShowing}
            appear={true}
            enter="transition-all ease-in-out duration-500"
            enterFrom="md:w-40vw md:max-w-md"
            enterTo="md:w-full md:max-w-full"
            className="bg-partner-primary-bg text-partner-primary-text py-12 px-10 md:h-screen flex flex-col justify-between md:w-40vw md:max-w-md flex-shrink-0">
            <div className="max-w-prose">
                <div className="md:min-h-48">
                    {window.extOnbData?.partnerLogo ? (
                        <div className="mb-8">
                            <img
                                style={{ maxWidth: '200px' }}
                                src={window.extOnbData.partnerLogo}
                                alt={window.extOnbData?.partnerName ?? ''}
                            />
                        </div>
                    ) : (
                        <Logo className="logo text-design-text w-32 sm:w-40 mb-8" />
                    )}
                    <div>
                        {info.map((step, index) => {
                            if (!index) {
                                return (
                                    <Transition
                                        appear={true}
                                        show={isShowing}
                                        enter="transition-opacity duration-1000"
                                        enterFrom="opacity-0"
                                        enterTo="opacity-100"
                                        leave="transition-opacity duration-1000"
                                        leaveFrom="opacity-100"
                                        leaveTo="opacity-0"
                                        className="text-4xl flex space-x-4 items-center"
                                        key={step}>
                                        {step}
                                    </Transition>
                                )
                            }
                        })}
                        <div className="flex space-x-4 items-center mt-6">
                            <Spinner className="spin" />
                            {infoDesc.map((step, index) => {
                                if (!index) {
                                    return (
                                        <Transition
                                            appear={true}
                                            show={isShowing}
                                            enter="transition-opacity duration-1000"
                                            enterFrom="opacity-0"
                                            enterTo="opacity-100"
                                            leave="transition-opacity duration-1000"
                                            leaveFrom="opacity-100"
                                            leaveTo="opacity-0"
                                            className="text-lg"
                                            key={step}>
                                            {step}
                                        </Transition>
                                    )
                                }
                            })}
                        </div>
                    </div>
                </div>
            </div>
        </Transition>
    )
}