/*
 * Copyright (c) 2023 AccelByte Inc. All Rights Reserved
 * This is licensed software from AccelByte Inc, for limitations
 * and restrictions contact your company contract manager.
 */

import {
  AppStore,
  AppStoreDetail,
  BundleStore,
  BundleStoreDetail,
  CodeStore,
  DlcStoreDetail,
  IngameItemStoreDetail,
  MultipleGameStore,
  OptionboxStore,
  OptionboxStoreDetail,
  SingleGameAppStore,
  SingleGameOptionboxStore,
  SingleGameStore,
  SingleGameStoreWrapper,
  SingleInGameItemsStore,
  StoreEntry,
  StoreWidget,
  storeFetcher
} from '@accelbyte/widgets-v2/widgets/store'
import { Outlet, RouteObject, json, useLoaderData, useOutletContext } from 'react-router'
import { sdk } from '../appConfig'
import { AppWrapper } from '../AppWrapper'
import React from 'react'
import { useParams } from 'react-router-dom'
import { BundleIcon } from '@accelbyte/widgets-v2/packages/od-components/components/Icons/BundleIcon'
import { GameIcon } from '@accelbyte/widgets-v2/packages/od-components/components/Icons/GameIcon'
import { OptionboxIcon } from '@accelbyte/widgets-v2/packages/od-components/components/Icons/OptionboxIcon'
import { ProductKeyIcon } from '@accelbyte/widgets-v2/packages/od-components/components/Icons/ProductKeyIcon'
import { Trans } from 'react-i18next'
import {
  storeAppsIndexFetcher,
  storeBundlesIndexFetcher,
  storeCodesIndexFetcher,
  storeDetailFetcher,
  storeDlcsIndexFetcher,
  storeInGameItemsIndexFetcher,
  storeItemsFetcher,
  storeOptionBoxesIndexFetcher
} from '@accelbyte/widgets-v2/widgets/store/storeFetcher'
import { ItemInfo } from '@accelbyte/sdk-platform'

const baseAppId = 'lightfantastic'

export const StoreRoute: RouteObject = {
  path: '/store',
  loader: async () => {
    const initialData = await storeFetcher({ sdk, appId: baseAppId, isSingleGame: false })
    return json(initialData)
  },
  Component: () => {
    const params = useParams()

    const initialData = useLoaderData() as Awaited<ReturnType<typeof storeFetcher>>

    return (
      <AppWrapper>
        <StoreWidget initialData={initialData}>
          {({ isSingleGame }) => {
            // Item detail.
            // We render the outlet right away.
            if (params.itemId) {
              return <Outlet />
            }

            let storeEntryContent: JSX.Element

            if (isSingleGame) {
              // Single game stuff.
              storeEntryContent = (
                <SingleGameStoreWrapper>
                  {({ baseItem }) => {
                    return (
                      <SingleGameStore
                        tabLinks={[
                          {
                            icon: <GameIcon className="icon" />,
                            label: <Trans i18nKey="AppDetailPage.dlcStore.heading">Expansions</Trans>,
                            link: '/store/dlcs'
                          },
                          {
                            icon: <BundleIcon className="icon" />,
                            label: <Trans i18nKey="AppDetailPage.inAppStore.heading">Game Store</Trans>,
                            link: '/store/in-game-items'
                          },
                          {
                            icon: <OptionboxIcon className="m-2" />,
                            label: <Trans i18nKey="StorePage.tabs.optionbox">Optionbox</Trans>,
                            link: '/store/optionboxes'
                          }
                        ]}>
                        <Outlet
                          context={{
                            isSingleGame,
                            storeProps: {
                              baseItem
                            }
                          }}
                        />
                      </SingleGameStore>
                    )
                  }}
                </SingleGameStoreWrapper>
              )
            } else {
              // Multiple game stuff.
              storeEntryContent = (
                <MultipleGameStore
                  tabLinks={[
                    {
                      icon: <GameIcon className="m-2" />,
                      link: '/store/apps',
                      label: <Trans i18nKey="StorePage.tabs.apps">Games</Trans>
                    },
                    {
                      icon: <BundleIcon className="m-2" />,
                      link: '/store/bundles',
                      label: <Trans i18nKey="StorePage.tabs.bundles">Bundles</Trans>
                    },
                    {
                      icon: <ProductKeyIcon className="m-2" />,
                      link: '/store/codes',
                      label: <Trans i18nKey="StorePage.tabs.productKeys">Product Keys</Trans>
                    },
                    {
                      icon: <OptionboxIcon className="m-2" />,
                      link: '/store/optionboxes',
                      label: <Trans i18nKey="StorePage.tabs.optionbox">Optionbox</Trans>
                    }
                  ]}>
                  <Outlet
                    context={{
                      isSingleGame
                    }}
                  />
                </MultipleGameStore>
              )
            }

            return <StoreEntry>{storeEntryContent}</StoreEntry>
          }}
        </StoreWidget>
      </AppWrapper>
    )

    //
  },
  children: [
    {
      path: '/store/dlcs',
      loader: async () => {
        const initialData = await storeDlcsIndexFetcher({ sdk, baseAppId })
        return json(initialData)
      },
      Component: () => {
        const props = useOutletContext() as { isSingleGame: boolean; storeProps?: { baseItem?: ItemInfo } }

        const loaderData = useLoaderData() as Awaited<ReturnType<typeof storeItemsFetcher>>

        if (!props) return null

        if (props.isSingleGame) {
          return <SingleGameAppStore baseItem={props.storeProps?.baseItem ?? null} initialData={loaderData.data} />
        }

        return <div>Not found</div>
      }
    },
    {
      path: '/store/in-game-items',
      loader: async () => {
        const initialData = await storeInGameItemsIndexFetcher({ sdk, baseAppId })
        return json(initialData)
      },
      Component: () => {
        const props = useOutletContext() as { isSingleGame: boolean; storeProps?: { baseItem?: ItemInfo } }
        const loaderData = useLoaderData() as Awaited<ReturnType<typeof storeItemsFetcher>>

        if (!props) return null

        if (props.isSingleGame) {
          return <SingleInGameItemsStore baseItem={props.storeProps?.baseItem ?? null} initialData={loaderData.data} />
        }

        return <div>Not found</div>
      }
    },
    {
      path: '/store/optionboxes',
      loader: async ({ request }) => {
        const url = new URL(request.url)
        const page = parseInt(url.searchParams.get('page') ?? '1')
        const isSingleGame = false
        const initialData = await storeOptionBoxesIndexFetcher({ sdk, isSingleGame, baseAppId, page })
        return json({ initialData, page })
      },
      Component: () => {
        const props = useOutletContext() as { isSingleGame: boolean; storeProps?: { baseItem?: ItemInfo } }
        const loaderData = useLoaderData() as { initialData: Awaited<ReturnType<typeof storeItemsFetcher>>; page: number }

        if (!props) return null

        if (props.isSingleGame) {
          return <SingleGameOptionboxStore baseItem={props.storeProps?.baseItem ?? null} initialData={loaderData.initialData.data} />
        }

        return <OptionboxStore page={loaderData.page} initialData={loaderData.initialData} />
      }
    },
    {
      path: '/store/apps',
      loader: async ({ request }) => {
        const url = new URL(request.url)
        const page = parseInt(url.searchParams.get('page') ?? '1')
        const initialData = await storeAppsIndexFetcher({ sdk, page })
        return json({ initialData, page })
      },
      Component: () => {
        const props = useOutletContext() as { isSingleGame: boolean; storeProps?: { baseItem?: ItemInfo } }
        const loaderData = useLoaderData() as { initialData: Awaited<ReturnType<typeof storeItemsFetcher>>; page: number }

        if (!props) return null

        if (props.isSingleGame) {
          return null
        }

        return <AppStore page={loaderData.page} initialData={loaderData.initialData} />
      }
    },
    {
      path: '/store/codes',
      loader: async ({ request }) => {
        const url = new URL(request.url)
        const page = parseInt(url.searchParams.get('page') ?? '1')
        const initialData = await storeCodesIndexFetcher({ sdk, page })
        return json({ initialData, page })
      },
      Component: () => {
        const props = useOutletContext() as { isSingleGame: boolean; storeProps?: { baseItem?: ItemInfo } }
        const loaderData = useLoaderData() as { initialData: Awaited<ReturnType<typeof storeItemsFetcher>>; page: number }

        if (!props) return null

        if (props.isSingleGame) {
          return null
        }

        return <CodeStore page={loaderData.page} initialData={loaderData.initialData} />
      }
    },
    {
      path: '/store/bundles',
      loader: async ({ request }) => {
        const url = new URL(request.url)
        const page = parseInt(url.searchParams.get('page') ?? '1')
        const initialData = await storeBundlesIndexFetcher({ sdk, page })

        return json({ initialData, page })
      },
      Component: () => {
        const props = useOutletContext() as { isSingleGame: boolean; storeProps?: { baseItem?: ItemInfo } }
        const loaderData = useLoaderData() as { initialData: Awaited<ReturnType<typeof storeItemsFetcher>>; page: number }

        if (!props) return null

        if (props.isSingleGame) {
          return null
        }

        return <BundleStore page={loaderData.page} initialData={loaderData.initialData} />
      }
    },
    // store details
    {
      path: '/store/dlcs/:itemId',
      loader: async ({ params }) => {
        const itemId = params.itemId ?? ''
        const { itemLocale, baseApp } = await storeDetailFetcher({ sdk, itemId, baseAppId })

        return json({ itemLocale, baseApp, itemId })
      },
      Component: () => {
        const loaderData = useLoaderData() as any
        return (
          <DlcStoreDetail itemId={loaderData?.itemId} initialItemLocale={loaderData?.itemLocale} initialBaseApp={loaderData?.baseApp} />
        )
      }
    },
    {
      path: '/store/in-game-items/:itemId',
      loader: async ({ params }) => {
        const itemId = params.itemId ?? ''
        const { itemLocale, baseApp } = await storeDetailFetcher({ sdk, itemId, baseAppId })

        return json({ itemLocale, baseApp, itemId })
      },
      Component: () => {
        const loaderData = useLoaderData() as any

        return (
          <IngameItemStoreDetail
            itemId={loaderData?.itemId}
            initialItemLocale={loaderData?.itemLocale}
            initialBaseApp={loaderData?.baseApp}
          />
        )
      }
    },
    {
      path: '/store/optionboxes/:itemId',
      loader: async ({ params }) => {
        const itemId = params.itemId ?? ''
        const { itemLocale, baseApp } = await storeDetailFetcher({ sdk, itemId })

        return json({ itemLocale, baseApp, itemId })
      },
      Component: () => {
        const loaderData = useLoaderData() as any

        return <OptionboxStoreDetail itemId={loaderData?.itemId} initialItemLocale={loaderData?.itemLocale} />
      }
    },
    {
      path: '/store/apps/:itemId',
      loader: async ({ params }) => {
        const itemId = params.itemId ?? ''
        const { itemLocale } = await storeDetailFetcher({ sdk, itemId })
        return json({ itemId, itemLocale })
      },
      Component: () => {
        const loaderData = useLoaderData() as any
        return <AppStoreDetail itemId={loaderData?.itemId} initialItemLocale={loaderData?.itemLocale} />
      }
    },
    {
      path: '/store/bundles/:itemId',
      loader: async ({ params }) => {
        const itemId = params.itemId ?? ''
        const { itemLocale, baseApp } = await storeDetailFetcher({ sdk, itemId, baseAppId })
        return json({ itemId, itemLocale, baseApp })
      },
      Component: () => {
        const loaderData = useLoaderData() as any
        return (
          <BundleStoreDetail itemId={loaderData?.itemId} initialItemLocale={loaderData?.itemLocale} initialBaseApp={loaderData?.baseApp} />
        )
      }
    }
  ]
}
