"use client"
import "react-international-phone/style.css"

import { isValidPhoneNumber, parsePhoneNumber } from "libphonenumber-js"
import { TextField } from "react-aria-components"
import { useController, useFormContext, useWatch } from "react-hook-form"
import {
  CountrySelector,
  DialCodePreview,
  type ParsedCountry,
  usePhoneInput,
} from "react-international-phone"
import { useIntl } from "react-intl"

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

import ErrorMessage from "@/components/TempDesignSystem/Form/ErrorMessage"
import AriaInputWithLabel from "@/components/TempDesignSystem/Form/Input/AriaInputWithLabel"
import Label from "@/components/TempDesignSystem/Form/Label"
import Body from "@/components/TempDesignSystem/Text/Body"
import useLang from "@/hooks/useLang"

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

import type { ChangeEvent } from "react"

import type {
  LowerCaseCountryCode,
  PhoneProps,
} from "@/types/components/form/phone"
import type { Lang } from "@/constants/languages"

export default function Phone({
  ariaLabel = "Phone number input",
  className = "",
  disabled = false,
  label,
  name = "phoneNumber",
  placeholder = "",
  readOnly = false,
  registerOptions = {
    required: true,
  },
}: PhoneProps) {
  const intl = useIntl()
  const lang = useLang()
  const { control, setValue, trigger } = useFormContext()
  const phone = useWatch({ name })

  const { field, fieldState, formState } = useController({
    control,
    disabled,
    name,
    rules: registerOptions,
  })

  const defaultPhoneNumber = formState.defaultValues?.phoneNumber

  // If defaultPhoneNumber exists and is valid, parse it to get the country code,
  // otherwise set the default country from the lang.
  const defaultCountry = isValidPhoneNumber(defaultPhoneNumber)
    ? parsePhoneNumber(defaultPhoneNumber).country?.toLowerCase()
    : getDefaultCountryFromLang(lang)

  const { country, handlePhoneValueChange, inputValue, setCountry } =
    usePhoneInput({
      defaultCountry,
      disableDialCodeAndPrefix: true,
      forceDialCode: true,
      value: phone,
      onChange: (value) => {
        // If not checked trigger(name) forces validation on mount
        // which shows error message before user even can see the form
        if (value.inputValue) {
          setValue(name, value.phone)
          trigger(name)
        } else {
          setValue(name, "")
        }
      },
    })

  function handleSelectCountry(value: ParsedCountry) {
    setCountry(value.iso2)
  }

  function handleChange(evt: ChangeEvent<HTMLInputElement>) {
    handlePhoneValueChange(evt)
  }

  return (
    <div className={`${styles.phone} ${className}`}>
      <CountrySelector
        disabled={readOnly}
        dropdownArrowClassName={styles.arrow}
        flagClassName={styles.flag}
        onSelect={handleSelectCountry}
        preferredCountries={["de", "dk", "fi", "no", "se", "gb"]}
        selectedCountry={country.iso2}
        renderButtonWrapper={(props) => (
          <button
            {...props.rootProps}
            className={styles.select}
            tabIndex={0}
            type="button"
            data-testid="country-selector"
          >
            <Label required={!!registerOptions.required} size="small">
              {intl.formatMessage({
                defaultMessage: "Country code",
              })}
            </Label>
            <span className={styles.selectContainer}>
              {props.children}
              <Body asChild fontOnly>
                <DialCodePreview
                  className={styles.dialCode}
                  dialCode={country.dialCode}
                  prefix="+"
                />
              </Body>
              <MaterialIcon
                icon="keyboard_arrow_down"
                className={styles.chevron}
                color="Icon/Default"
                size={18}
              />
            </span>
          </button>
        )}
      />
      <TextField
        aria-label={ariaLabel}
        defaultValue={field.value}
        isDisabled={disabled ?? field.disabled}
        isInvalid={fieldState.invalid}
        isRequired={!!registerOptions?.required}
        isReadOnly={readOnly}
        name={field.name}
        type="tel"
      >
        <AriaInputWithLabel
          {...field}
          autoComplete="tel-national"
          id={field.name}
          label={label}
          onChange={handleChange}
          placeholder={placeholder}
          readOnly={readOnly}
          required={!!registerOptions.required}
          type="tel"
          value={inputValue}
        />
        <ErrorMessage errors={formState.errors} name={field.name} />
      </TextField>
    </div>
  )
}

function getDefaultCountryFromLang(lang: Lang): LowerCaseCountryCode {
  const countryMap: Record<Lang, LowerCaseCountryCode> = {
    sv: "se",
    da: "dk",
    fi: "fi",
    no: "no",
    de: "de",
    en: "se", // Default to Sweden for English
  }
  return countryMap[lang] || "se"
}
