"use client"

import { useState } from "react"
import { useIntl } from "react-intl"

import { useScrollToTop } from "@scandic-hotels/common/hooks/useScrollToTop"
import { BackToTopButton } from "@scandic-hotels/design-system/BackToTopButton"
import { LoadingSpinner } from "@scandic-hotels/design-system/LoadingSpinner"
import SidePeekSelfControlled from "@scandic-hotels/design-system/SidePeekSelfControlled"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"

import useLang from "@/hooks/useLang"

import ShowMoreButton from "../../ShowMoreButton"
import { Card } from "../Card"
import { groupStaysByYear } from "../utils/groupStaysByYear"

import styles from "./previousStaysSidePeek.module.css"

import type { PreviousStaysNonNullResponseObject } from "@/types/components/myPages/stays/previous"

interface PreviousStaysSidePeekProps {
  isOpen: boolean
  onClose: () => void
}

export function PreviousStaysSidePeek({
  isOpen,
  onClose,
}: PreviousStaysSidePeekProps) {
  const intl = useIntl()
  const lang = useLang()

  const [scrollContainer, setScrollContainer] = useState<HTMLElement | null>(
    null
  )

  const scrollContainerRef = (node: HTMLDivElement | null) => {
    const parent = node?.parentElement
    // SidePeekSelfControlled renders children twice: in the modal & in an sr-only SEO wrapper.
    // We filter out the SEO wrapper to get the actual scrollable container.
    if (parent && !parent.classList.contains("sr-only")) {
      setScrollContainer(parent)
    }
  }

  const { showBackToTop, scrollToTop } = useScrollToTop({
    threshold: 200,
    element: scrollContainer,
    refScrollable: true,
  })

  const { data, isFetching, fetchNextPage, hasNextPage, isLoading } =
    trpc.user.stays.previous.useInfiniteQuery(
      {
        limit: 10,
        lang,
      },
      {
        getNextPageParam: (lastPage) => {
          return lastPage?.nextCursor
        },
        enabled: isOpen,
      }
    )

  function loadMoreData() {
    if (hasNextPage) {
      fetchNextPage()
    }
  }

  const stays = data?.pages
    .filter((page): page is PreviousStaysNonNullResponseObject => !!page?.data)
    .flatMap((page) => page.data)

  const staysByYear = stays ? groupStaysByYear(stays) : []

  return (
    <SidePeekSelfControlled
      title={intl.formatMessage({
        id: "stays.previous.title",
        defaultMessage: "Previous stays",
      })}
      isOpen={isOpen}
      onClose={onClose}
    >
      <div ref={scrollContainerRef} className={styles.content}>
        {isLoading ? (
          <div className={styles.loadingContainer}>
            <LoadingSpinner />
          </div>
        ) : (
          <>
            {staysByYear.map(({ year, stays }) => (
              <section key={year} className={styles.yearSection}>
                <div className={styles.yearHeader}>
                  <Typography variant="Title/Overline/sm">
                    <span className={styles.yearText}>{year}</span>
                  </Typography>
                </div>
                <div className={styles.staysList}>
                  {stays.map((stay) => (
                    <Card
                      key={stay.attributes.confirmationNumber}
                      stay={stay}
                    />
                  ))}
                </div>
              </section>
            ))}
            {hasNextPage && (
              <ShowMoreButton
                disabled={isFetching}
                loadMoreData={loadMoreData}
              />
            )}
          </>
        )}
        {showBackToTop && !isLoading && (
          <BackToTopButton
            label={intl.formatMessage({
              id: "common.backToTop",
              defaultMessage: "Back to top",
            })}
            onPress={scrollToTop}
            position="right"
          />
        )}
      </div>
    </SidePeekSelfControlled>
  )
}
