'use client';

import { signIn } from 'next-auth/react';
import { useState } from 'react';
import { OtpLoginFormType, FormType, PzSignInOptions } from '@theme/types';
import { Button, Input } from '@theme/components';
import { SubmitHandler, useForm } from 'react-hook-form';
import * as yup from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';
import clsx from 'clsx';
import { useLocalization } from '@akinon/next/hooks';
import { useOtpLoginMutation } from '@akinon/next/data/client/user';
import { useAppDispatch, useAppSelector } from '@akinon/next/redux/hooks';
import PluginModule, { Component } from '@akinon/next/components/plugin-module';
import { AuthError } from '@akinon/next/types';
import { showPopup } from '@akinon/pz-otp/src/redux/reducer';

const loginFormSchema = (t) =>
  yup.object().shape({
    phone: yup
      .string()
      .transform((value: string) => value?.replace(/_/g, '').replace(/ /g, ''))
      .length(11, t('account.my_profile.form.phone.error.not_valid'))
      .required(t('auth.login.form.error.required')),
    code: yup.string()
  });

export const OtpLogin = () => {
  const dispatch = useAppDispatch();
  const { user_phone_format } = useAppSelector((state) => state.config);
  const { t, locale } = useLocalization();
  const [otpLoginMutation] = useOtpLoginMutation();

  const {
    register,
    handleSubmit,
    formState: { errors },
    getValues,
    control
  } = useForm<OtpLoginFormType>({
    resolver: yupResolver(loginFormSchema(t))
  });

  const [formError, setFormError] = useState(null);

  const loginHandler: SubmitHandler<OtpLoginFormType> = async (data) => {
    const loginResponse = await signIn('default', {
      redirect: false,
      callbackUrl: '/',
      ...data,
      formType: FormType.otpLogin
    } as PzSignInOptions & { redirect: false });

    if (loginResponse.error) {
      const errors: AuthError[] = JSON.parse(loginResponse.code);

      const fieldErrors = errors.find((error) => error.type === 'field_errors')
        ?.data as { name: string; value: string[] }[];

      const nonFieldErrors = errors.find(
        (error) => error.type === 'non_field_errors'
      )?.data as string[];

      fieldErrors?.forEach((item) => {
        if (item.name === 'error_code') {
          setFormError(t('auth.otp_login.form.error_code'));
        }
      });

      if (nonFieldErrors?.length) {
        setFormError(nonFieldErrors.join(', '));
      }

      return;
    }
  };

  const onSubmit = async (data: OtpLoginFormType) => {
    await otpLoginMutation({
      phone: data.phone
    })
      .unwrap()
      .then(() => {
        dispatch(showPopup());
      })
      .catch((error) => {
        if (error.status === 429) {
          setFormError(t('auth.login.form.error.too_many_requests'));
          return;
        }

        for (const key in error.data) {
          setFormError(error.data[key]);
        }
      });
  };

  return (
    <section className={clsx(['w-full py-10 md:py-0 md:mx-auto'])}>
      <h2 className="mb-3 text-lg text-start text-black-800 font-light md:mb-9 md:text-2xl">
        {t('auth.login.title_gsm')}
      </h2>
      <form onSubmit={handleSubmit(onSubmit)}>
        <input
          type="hidden"
          value={FormType.otpLogin}
          {...register('formType')}
        />
        <input type="hidden" value={locale} {...register('locale')} />

        <div className="mb-4">
          <Input
            labelStyle="floating"
            className="h-14"
            label={t('auth.login.form.phone.placeholder')}
            type="tel"
            format={user_phone_format.replace(/9/g, '#')}
            mask="_"
            allowEmptyFormatting={true}
            control={control}
            {...register('phone')}
            error={errors.phone}
            required
          />
        </div>

        {formError && (
          <p
            className="text-error text-xs mb-4"
            data-testid="login-error-field"
          >
            {formError}
          </p>
        )}

        <Button
          className="w-full h-12 uppercase text-xs font-semibold"
          type="submit"
          data-testid="otp-login-submit"
        >
          {t('auth.login.form.submit')}
        </Button>
      </form>

      <PluginModule
        component={Component.Otp}
        props={{
          data: getValues(),
          submitAction: loginHandler,
          error: formError
        }}
      />
    </section>
  );
};
