"use client"

import { useMap } from "@vis.gl/react-google-maps"
import { cx } from "class-variance-authority"
import { useState } from "react"
import { Button as ButtonRAC } from "react-aria-components"
import { useIntl } from "react-intl"

import { Typography } from "@scandic-hotels/design-system/Typography"

import PoiMarker from "@/components/Maps/Markers/Poi"

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

import type { SidebarProps } from "@/types/components/hotelPage/map/sidebar"
import type { Coordinates } from "@/types/components/maps/coordinates"
import { PointOfInterestGroupEnum } from "@/types/enums/pointOfInterest"

export default function Sidebar({
  activePoi,
  hotelName,
  pointsOfInterest,
  onActivePoiChange,
  coordinates,
}: SidebarProps) {
  const intl = useIntl()
  const map = useMap()
  const [isFullScreenSidebar, setIsFullScreenSidebar] = useState(false)
  const [isClicking, setIsClicking] = useState(false)
  const poiGroups = new Set(pointsOfInterest.map(({ group }) => group))
  const poisInGroups = Array.from(poiGroups).map((group) => ({
    group,
    pois: pointsOfInterest.filter((poi) => poi.group === group),
  }))

  function toggleFullScreenSidebar() {
    setIsFullScreenSidebar((prev) => !prev)
  }

  function moveToPoi(poiCoordinates: Coordinates) {
    if (map) {
      const hotelLatLng = new google.maps.LatLng(
        coordinates.lat,
        coordinates.lng
      )
      const poiLatLng = new google.maps.LatLng(
        poiCoordinates.lat,
        poiCoordinates.lng
      )

      const bounds = new google.maps.LatLngBounds()
      bounds.extend(hotelLatLng)
      bounds.extend(poiLatLng)

      map.fitBounds(bounds)

      const currentZoomLevel = map.getZoom()

      if (currentZoomLevel) {
        map.setZoom(currentZoomLevel - 1)
      }
    }
  }

  function handleMouseEnter(poiName: string | undefined) {
    if (!poiName) return

    if (!isClicking) {
      onActivePoiChange(poiName)
    }
  }

  function handlePoiClick(
    poiName: string | undefined,
    poiCoordinates: Coordinates
  ) {
    if (!poiName || !poiCoordinates) return

    setIsClicking(true)
    toggleFullScreenSidebar()
    onActivePoiChange(poiName)
    moveToPoi(poiCoordinates)
    setTimeout(() => {
      setIsClicking(false)
    }, 200)
  }

  const viewAsMapMsg = intl.formatMessage({
    defaultMessage: "View as map",
  })
  const viewAsListMsg = intl.formatMessage({
    defaultMessage: "View as list",
  })

  function translatePOIGroup(group: PointOfInterestGroupEnum) {
    switch (group) {
      case PointOfInterestGroupEnum.PUBLIC_TRANSPORT:
        return intl.formatMessage({
          defaultMessage: "Public transport",
        })
      case PointOfInterestGroupEnum.ATTRACTIONS:
        return intl.formatMessage({
          defaultMessage: "Attractions",
        })
      case PointOfInterestGroupEnum.BUSINESS:
        return intl.formatMessage({
          defaultMessage: "Business",
        })
      case PointOfInterestGroupEnum.LOCATION:
        return intl.formatMessage({
          defaultMessage: "Location",
        })
      case PointOfInterestGroupEnum.PARKING:
        return intl.formatMessage({
          defaultMessage: "Parking",
        })
      case PointOfInterestGroupEnum.SHOPPING_DINING:
        return intl.formatMessage({
          defaultMessage: "Shopping & Dining",
        })
      default:
        const option: never = group
        console.warn(`Unsupported group given: ${option}`)

        return intl.formatMessage({
          defaultMessage: "N/A",
        })
    }
  }

  return (
    <>
      <aside
        className={`${styles.sidebar} ${
          isFullScreenSidebar ? styles.fullscreen : ""
        }`}
      >
        <Typography variant="Body/Paragraph/mdBold">
          <ButtonRAC
            className={styles.sidebarToggle}
            onPress={toggleFullScreenSidebar}
          >
            {isFullScreenSidebar ? viewAsMapMsg : viewAsListMsg}
          </ButtonRAC>
        </Typography>
        <div className={styles.sidebarContent}>
          <Typography variant="Title/sm">
            <h1 className={styles.title}>
              {intl.formatMessage(
                {
                  defaultMessage: "Things nearby {hotelName}",
                },
                { hotelName }
              )}
            </h1>
          </Typography>

          {poisInGroups.map(({ group, pois }) =>
            pois.length ? (
              <div key={group} className={styles.poiGroup}>
                <Typography variant="Body/Paragraph/mdBold">
                  <h3 className={styles.poiHeading}>
                    <PoiMarker group={group} />
                    {translatePOIGroup(group)}
                  </h3>
                </Typography>
                <ul className={styles.poiList}>
                  {pois.map((poi) => (
                    <li key={poi.name} className={styles.poiItem}>
                      <Typography variant="Body/Paragraph/mdRegular">
                        <ButtonRAC
                          className={cx(styles.poiButton, {
                            [styles.active]: activePoi === poi.name,
                          })}
                          onHoverStart={() => handleMouseEnter(poi.name)}
                          onPress={() =>
                            handlePoiClick(poi.name, poi.coordinates)
                          }
                        >
                          <span>{poi.name}</span>
                          <span>
                            {intl.formatMessage(
                              {
                                defaultMessage: "{distanceInKm} km",
                              },
                              {
                                distanceInKm: poi.distance,
                              }
                            )}
                          </span>
                        </ButtonRAC>
                      </Typography>
                    </li>
                  ))}
                </ul>
              </div>
            ) : null
          )}
        </div>
      </aside>
      <div className={styles.backdrop} onClick={toggleFullScreenSidebar} />
    </>
  )
}
