import { notFound } from "next/navigation"
import { Suspense } from "react"

import {
  getHotel,
  getHotelPage,
  getMeetingRooms,
} from "@/lib/trpc/memoizedRequests"

import AccordionSection from "@/components/Blocks/Accordion"
import Breadcrumbs from "@/components/Breadcrumbs"
import Alert from "@/components/TempDesignSystem/Alert"
import BreadcrumbsSkeleton from "@/components/TempDesignSystem/Breadcrumbs/BreadcrumbsSkeleton"
import TrackingSDK from "@/components/TrackingSDK"
import { getIntl } from "@/i18n"
import { getLang } from "@/i18n/serverContext"
import { setFacilityCards } from "@/utils/facilityCards"
import { generateHotelSchema } from "@/utils/jsonSchemas"
import { safeTry } from "@/utils/safeTry"

import MapCard from "./Map/MapCard"
import MapWithCardWrapper from "./Map/MapWithCard"
import MobileMapToggle from "./Map/MobileMapToggle"
import StaticMap from "./Map/StaticMap"
import AboutTheHotelSidePeek from "./SidePeeks/AboutTheHotel"
import ActivitiesSidePeek from "./SidePeeks/Activities"
import AmenitiesSidePeek from "./SidePeeks/Amenities"
import MeetingsAndConferencesSidePeek from "./SidePeeks/MeetingsAndConferences"
import RestaurantBarSidePeek from "./SidePeeks/RestaurantBar"
import RoomSidePeek from "./SidePeeks/Room"
import WellnessAndExerciseSidePeek from "./SidePeeks/WellnessAndExercise"
import AmenitiesList from "./AmenitiesList"
import Facilities from "./Facilities"
import IntroSection from "./IntroSection"
import PreviewImages from "./PreviewImages"
import { Rooms } from "./Rooms"
import SidePeeks from "./SidePeeks"
import TabNavigation from "./TabNavigation"
import {
  getPageSectionsData,
  getTrackingHotelData,
  getTrackingPageData,
} from "./utils"

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

import type { HotelPageProps } from "@/types/components/hotelPage/hotelPage"
import { AlertName } from "@/types/enums/alert"
import { HotelHashValues } from "@/types/enums/hotelPage"

export default async function HotelPage({ hotelId }: HotelPageProps) {
  const lang = await getLang()
  const intl = await getIntl()

  void getHotelPage()
  void getHotel({
    hotelId,
    isCardOnlyPayment: false,
    language: lang,
  })

  const hotelPageData = await getHotelPage()
  const hotelData = await getHotel({
    hotelId,
    isCardOnlyPayment: false,
    language: lang,
  })

  const [meetingRoomsData] = await safeTry(
    getMeetingRooms({ hotelId, language: lang })
  )

  if (!hotelData?.hotel || !hotelPageData) {
    return notFound()
  }

  const jsonSchema = generateHotelSchema(hotelData)
  const {
    faq,
    content: { spaPage, activitiesCards },
    sectionHeadings,
  } = hotelPageData
  const { hotel, restaurants, roomCategories, additionalData } = hotelData
  const {
    name,
    address,
    pointsOfInterest,
    specialAlerts,
    hotelContent,
    detailedFacilities,
    healthFacilities,
    contactInformation,
    socialMedia,
    hotelFacts,
    location,
    ratings,
    parking,
    hotelType,
  } = hotel
  const {
    healthAndWellness,
    healthAndFitness,
    restaurantImages,
    conferencesAndMeetings,
    hotelRoomElevatorPitchText,
    gallery,
    hotelParking,
    meetingRooms,
    displayWebPage,
    hotelSpecialNeeds,
  } = additionalData

  const images = gallery?.smallerImages
  const description = hotelContent.texts.descriptions?.medium
  const pageSections = getPageSectionsData(
    intl,
    {
      hasWellness: healthFacilities.length > 0,
      hasRestaurants: restaurants.length > 0,
      hasMeetingRooms: !!(meetingRoomsData && meetingRoomsData.length > 0),
      hasActivities: activitiesCards.length > 0,
      hasFAQ: !!(faq && faq.accordions.length > 0),
    },
    sectionHeadings
  )

  const facilities = setFacilityCards(
    restaurantImages ?? undefined,
    conferencesAndMeetings ?? undefined,
    healthAndWellness ?? undefined,
    pageSections
  )

  const coordinates = {
    lat: location.latitude,
    lng: location.longitude,
  }

  const trackingPageData = getTrackingPageData(
    hotelPageData.system,
    hotelData.hotel,
    lang
  )
  const trackingHotelData = getTrackingHotelData(hotelData.hotel)

  return (
    <div className={styles.pageContainer}>
      <script
        type={jsonSchema.type}
        dangerouslySetInnerHTML={{
          __html: JSON.stringify(jsonSchema.jsonLd),
        }}
      />
      <header className={styles.header}>
        <Suspense fallback={<BreadcrumbsSkeleton size="headerWidth" />}>
          <Breadcrumbs size="headerWidth" />
        </Suspense>
        {images?.length ? (
          <PreviewImages images={images} hotelName={name} />
        ) : null}
      </header>
      <TabNavigation pageSections={pageSections} />

      <main className={styles.mainSection}>
        <div id={HotelHashValues.overview} className={styles.overview}>
          <div className={styles.introContainer}>
            <IntroSection
              hotelName={name}
              hotelDescription={description}
              location={location}
              address={address}
              tripAdvisor={ratings?.tripAdvisor}
            />

            <AmenitiesList detailedFacilities={detailedFacilities} />
          </div>
          {specialAlerts.length ? (
            <div className={styles.alertsContainer}>
              {specialAlerts
                .filter(
                  (alert) => alert.name !== AlertName.HotelChildrenInBooking
                )
                .map((alert) => (
                  <Alert
                    key={alert.id}
                    type={alert.type}
                    heading={alert.heading}
                    text={alert.text}
                  />
                ))}
            </div>
          ) : null}
        </div>
        <Rooms
          heading={pageSections.rooms.heading}
          rooms={roomCategories}
          preamble={hotelRoomElevatorPitchText}
        />
        {facilities && (
          <Facilities
            facilities={facilities}
            activitiesCards={activitiesCards}
            amenities={detailedFacilities}
            healthFacilities={healthFacilities}
          />
        )}
        {faq && faq.accordions.length > 0 && (
          <AccordionSection accordion={faq.accordions} title={faq.title} />
        )}
      </main>
      <aside className={styles.mapContainer}>
        <MapWithCardWrapper>
          <StaticMap
            coordinates={coordinates}
            hotelName={name}
            markerInfo={{ hotelType, hotelId }}
          />
          <MapCard hotelName={name} pois={pointsOfInterest.slice(0, 3)} />
        </MapWithCardWrapper>
      </aside>
      <MobileMapToggle />
      <SidePeeks hotelId={hotelId}>
        <AmenitiesSidePeek
          amenitiesList={detailedFacilities}
          parking={{
            parking: parking,
            parkingElevatorPitch: hotelParking.elevatorPitch,
            parkingPageUrl: displayWebPage.parking
              ? hotelParking.nameInUrl
              : undefined,
          }}
          checkInInformation={hotelFacts.checkin}
          accessibility={{
            elevatorPitch: hotelSpecialNeeds.elevatorPitch,
            accessibilityPageUrl: displayWebPage.specialNeeds
              ? hotelSpecialNeeds.nameInUrl
              : undefined,
          }}
          restaurants={restaurants}
          hotelType={hotelType}
        />
        <AboutTheHotelSidePeek
          hotelAddress={address}
          coordinates={location}
          contact={contactInformation}
          socials={socialMedia}
          ecoLabels={hotelFacts.ecoLabels}
          descriptions={hotelContent.texts}
        />
        {pageSections.wellness ? (
          <WellnessAndExerciseSidePeek
            heading={pageSections.wellness.heading}
            healthFacilities={healthFacilities}
            spaPage={spaPage?.spa_page}
            wellnessExercisePageUrl={
              displayWebPage.healthGym ? healthAndFitness.nameInUrl : undefined
            }
          />
        ) : null}
        {pageSections.restaurant ? (
          <RestaurantBarSidePeek
            heading={pageSections.restaurant.heading}
            restaurants={restaurants}
          />
        ) : null}
        {activitiesCards.map((card) => (
          <ActivitiesSidePeek
            key={card.upcoming_activities_card.heading}
            contentPage={card.upcoming_activities_card.contentPage}
            sidepeekCTA={card.upcoming_activities_card.sidepeekCtaText}
            sidepeekSlug={card.upcoming_activities_card.sidepeekSlug}
          />
        ))}
        {pageSections.meetings ? (
          <MeetingsAndConferencesSidePeek
            heading={pageSections.meetings.heading}
            meetingFacilities={conferencesAndMeetings}
            descriptions={hotelContent.texts.meetingDescription}
            meetingRooms={meetingRoomsData ?? []}
            meetingPageUrl={
              displayWebPage.meetingRoom ? meetingRooms.nameInUrl : undefined
            }
          />
        ) : null}
        {roomCategories.map((room) => (
          <RoomSidePeek key={room.name} hotelId={hotelId} room={room} />
        ))}
      </SidePeeks>
      <Suspense fallback={null}>
        <TrackingSDK
          pageData={trackingPageData}
          hotelInfo={trackingHotelData}
        />
      </Suspense>
    </div>
  )
}
