"use client"

import { useState } from "react"
import { TextField } from "react-aria-components"
import {
  Controller,
  type RegisterOptions,
  useFormContext,
} from "react-hook-form"
import { useIntl } from "react-intl"

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

import { getErrorMessage } from "@/utils/getErrorMessage"

import { NewPasswordValidation } from "./NewPasswordValidation"

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

interface PasswordInputProps
  extends React.InputHTMLAttributes<HTMLInputElement> {
  label?: string
  registerOptions?: RegisterOptions
  visibilityToggleable?: boolean
  isNewPassword?: boolean
}

export default function PasswordInput({
  name = "password",
  label,
  "aria-label": ariaLabel,
  disabled = false,
  placeholder,
  registerOptions = {},
  visibilityToggleable = true,
  isNewPassword = false,
  className = "",
}: PasswordInputProps) {
  const { control } = useFormContext()
  const intl = useIntl()
  const [isPasswordVisible, setIsPasswordVisible] = useState(false)

  return (
    <Controller
      disabled={disabled}
      control={control}
      name={name}
      rules={registerOptions}
      render={({ field, fieldState, formState }) => {
        const errors = isNewPassword
          ? Object.values(formState.errors[name]?.types ?? []).flat()
          : []

        return (
          <TextField
            className={className}
            aria-label={ariaLabel}
            aria-invalid={!!fieldState.error}
            aria-describedby="password-error password-requirements"
            isDisabled={field.disabled}
            isInvalid={fieldState.invalid}
            isRequired={!!registerOptions.required}
            name={field.name}
            onBlur={field.onBlur}
            onChange={field.onChange}
            validationBehavior="aria"
            value={field.value}
            type={
              visibilityToggleable && isPasswordVisible ? "text" : "password"
            }
          >
            <div className={styles.inputWrapper}>
              <Input
                {...field}
                aria-labelledby={field.name}
                id={field.name}
                label={
                  label ||
                  (isNewPassword
                    ? intl.formatMessage({
                        id: "passwordInput.newPasswordLabel",
                        defaultMessage: "New password",
                      })
                    : intl.formatMessage({
                        id: "common.password",
                        defaultMessage: "Password",
                      }))
                }
                placeholder={placeholder}
                type={
                  visibilityToggleable && isPasswordVisible
                    ? "text"
                    : "password"
                }
              />
              {visibilityToggleable ? (
                <IconButton
                  variant="Muted"
                  emphasis
                  onPress={() => setIsPasswordVisible((value) => !value)}
                  aria-label={
                    isPasswordVisible
                      ? intl.formatMessage({
                          id: "passwordInput.hidePassword",
                          defaultMessage: "Hide password",
                        })
                      : intl.formatMessage({
                          id: "passwordInput.showPassword",
                          defaultMessage: "Show password",
                        })
                  }
                  aria-controls={field.name}
                  className={styles.toggleButton}
                >
                  <MaterialIcon
                    icon={isPasswordVisible ? "visibility_off" : "visibility"}
                    size={24}
                  />
                </IconButton>
              ) : null}
            </div>

            {isNewPassword ? (
              <NewPasswordValidation value={field.value} errors={errors} />
            ) : null}

            {isNewPassword ? (
              !field.value && fieldState.error ? (
                <ErrorMessage errorMessage={fieldState.error.message} />
              ) : null
            ) : fieldState.error ? (
              <ErrorMessage errorMessage={fieldState.error.message} />
            ) : null}
          </TextField>
        )
      }}
    />
  )
}

function ErrorMessage({ errorMessage }: { errorMessage?: string }) {
  const intl = useIntl()
  return (
    <Typography
      variant="Body/Supporting text (caption)/smRegular"
      className={styles.error}
    >
      <p role="alert" id="password-error">
        <MaterialIcon
          icon="info"
          color="Icon/Feedback/Error"
          aria-label={intl.formatMessage({
            id: "common.error",
            defaultMessage: "Error",
          })}
        />
        {getErrorMessage(intl, errorMessage)}
      </p>
    </Typography>
  )
}
