"use client"
import { useState } from "react"
import {
  Button,
  ComboBox,
  Input,
  type Key,
  ListBox,
  ListBoxItem,
  Popover,
} from "react-aria-components"
import { useController, useFormContext } from "react-hook-form"
import { useIntl } from "react-intl"

import { countries } from "@/constants/countries"

import Label from "@/components/TempDesignSystem/Form/Label"
import SelectChevron from "@/components/TempDesignSystem/Form/SelectChevron"
import Body from "@/components/TempDesignSystem/Text/Body"
import useLang from "@/hooks/useLang"

import ErrorMessage from "../ErrorMessage"

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

import type {
  CountryPortalContainer,
  CountryPortalContainerArgs,
  CountryProps,
} from "./country"

export default function CountrySelect({
  className = "",
  label,
  name = "country",
  readOnly = false,
  registerOptions = {},
}: CountryProps) {
  const lang = useLang()
  const intl = useIntl()
  const [rootDiv, setRootDiv] = useState<CountryPortalContainer>(undefined)

  function setRef(node: CountryPortalContainerArgs) {
    if (node) {
      setRootDiv(node)
    }
  }
  const { control, setValue } = useFormContext()
  const { field, formState } = useController({
    control,
    name,
    rules: registerOptions,
  })

  function handleChange(country: Key | null) {
    setValue(name, country ?? "")
  }

  const selectCountryLabel = intl.formatMessage({
    defaultMessage: "Select a country",
  })
  const collator = new Intl.Collator(lang)

  return (
    <div className={`${styles.container} ${className}`} ref={setRef}>
      <ComboBox
        aria-label={intl.formatMessage({
          defaultMessage: "Select country of residence",
        })}
        isReadOnly={readOnly}
        isRequired={!!registerOptions?.required}
        name={field.name}
        onBlur={field.onBlur}
        onSelectionChange={handleChange}
        ref={field.ref}
        selectedKey={field.value}
        data-testid={name}
      >
        <div className={styles.comboBoxContainer}>
          <Label
            className={styles.label}
            size="small"
            required={!!registerOptions.required}
          >
            {label}
          </Label>
          <Body asChild fontOnly>
            <Input
              aria-label={selectCountryLabel}
              className={styles.input}
              placeholder={selectCountryLabel}
            />
          </Body>
          <Button className={styles.button}>
            <SelectChevron />
          </Button>
        </div>
        <ErrorMessage errors={formState.errors} name={name} />
        <Popover
          className={styles.popover}
          placement="bottom"
          shouldFlip={false}
          shouldUpdatePosition={false}
          /**
           * react-aria uses portals to render Popover in body
           * unless otherwise specified. We need it to be contained
           * by this component to both access css variables assigned
           * on the container as well as to not overflow it at any time.
           */
          UNSTABLE_portalContainer={rootDiv}
        >
          <ListBox>
            {countries
              .map((country) => ({
                ...country,
                localizedDisplayName:
                  intl.formatDisplayName(country.code, { type: "region" }) ||
                  country.name,
              }))
              .sort((a, b) =>
                collator.compare(a.localizedDisplayName, b.localizedDisplayName)
              )
              .map((country, idx) => {
                return (
                  <Body asChild fontOnly key={`${country.code}-${idx}`}>
                    <ListBoxItem
                      aria-label={country.name}
                      className={styles.listBoxItem}
                      id={country.code}
                    >
                      {country.localizedDisplayName}
                    </ListBoxItem>
                  </Body>
                )
              })}
          </ListBox>
        </Popover>
      </ComboBox>
    </div>
  )
}
