import { useState, useRef, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import parsePhoneNumberFromString from 'libphonenumber-js';
import { PageWrapper } from '../PageWrapper';
import { CardContainer } from '@/components/CardContainer';
import PhoneDisplay from './phoneNumber/PhoneDisplay';
import PhoneEditForm from './phoneNumber/PhoneEditForm';
import PhoneActionButtons from './phoneNumber/PhoneActionButtons';
import { CircularProgress, Box, Typography } from '@mui/material';
import { toLocaleDigits } from '@/utils/persianDigit';
import { useApi } from '@/hooks/useApi';
import {
  fetchProfile,
  sendVerificationCode,
  confirmPhoneNumberCode,
  changePhoneNumber,
} from '../../api/settingsApi';
import { type Phone } from '../../types/settingsType';
import { useToast } from '@rkheftan/harmony-ui';

export function PhoneNumber() {
  const { t, i18n } = useTranslation('setting');
  const toast = useToast();
  const [isEditing, setIsEditing] = useState(false);
  const [phoneNumber, setPhoneNumber] = useState('');
  const [verificationCode, setVerificationCode] = useState('');
  const [showToast, setShowToast] = useState(false);
  const [buttonState, setButtonState] = useState<'default' | 'counting'>(
    'default',
  );
  const [isVerified, setIsVerified] = useState(false);
  const [phones, setPhones] = useState<Phone[]>([]);
  const [countryCode, setCountryCode] = useState('+98');
  const [formError, setFormError] = useState<string>();
  const [touched, setTouched] = useState<boolean>(false);

  const textFieldRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  const {
    data: profileData,
    loading: isLoading,
    error: fetchError,
  } = useApi(fetchProfile, { immediate: true });

  const {
    data: sendCodeData,
    loading: isSendingCode,
    error: sendCodeError,
    execute: executeSendCode,
  } = useApi(sendVerificationCode);

  const {
    data: confirmData,
    loading: isVerifying,
    error: confirmError,
    execute: executeConfirmCode,
  } = useApi(confirmPhoneNumberCode);

  const {
    data: changePhoneData,
    loading: isChangingPhone,
    error: changePhoneError,
    execute: executeChangePhone,
  } = useApi(changePhoneNumber);

  useEffect(() => {
    if (profileData?.success && profileData.phoneNumber) {
      setPhones([
        {
          phone: profileData.phoneNumber,
          time: '',
          withCode: profileData.phoneNumber,
        },
      ]);
    }
  }, [profileData]);

  useEffect(() => {
    if (fetchError) {
      toast({
        message:
          getErrorMessage(fetchError) || t('settingForm.errorFetchPhoneNumber'),
        severity: 'error',
      });
    }
  }, [fetchError, toast, t]);

  useEffect(() => {
    if (sendCodeData?.success) {
      setButtonState('counting');
      setIsVerified(false);
      toast({
        message: t('settingForm.codeSentSuccessfully'),
        severity: 'success',
      });
    }
  }, [sendCodeData, t, toast]);

  useEffect(() => {
    if (sendCodeError) {
      toast({
        message:
          getErrorMessage(sendCodeError) || t('settingForm.errorSendCode'),
        severity: 'error',
      });
    }
  }, [sendCodeError, toast, t]);

  useEffect(() => {
    if (confirmData?.success && confirmData.confirm) {
      setIsVerified(true);
      setShowToast(true);
      const fullPhoneNumber = countryCode + phoneNumber.replace(/^0/, '');
      executeChangePhone({ phoneNumber: fullPhoneNumber });
      toast({
        message: t('settingForm.phoneVerified'),
        severity: 'success',
      });
    }
  }, [confirmData, countryCode, phoneNumber, executeChangePhone, t, toast]);

  useEffect(() => {
    if (confirmError) {
      toast({
        message:
          getErrorMessage(confirmError) || t('settingForm.errorConfirmCode'),
        severity: 'error',
      });
    }
  }, [confirmError, toast, t]);

  useEffect(() => {
    if (changePhoneData?.success) {
      const fullPhoneNumber = countryCode + phoneNumber.replace(/^0/, '');
      setPhones([
        {
          phone: phoneNumber,
          time: t('settingForm.justNow'),
          withCode: fullPhoneNumber,
        },
      ]);
      setIsEditing(false);
      toast({
        message: t('settingForm.phoneChangedSuccessfully'),
        severity: 'success',
      });
    }
  }, [changePhoneData, countryCode, phoneNumber, t, toast]);

  useEffect(() => {
    if (changePhoneError) {
      toast({
        message:
          getErrorMessage(changePhoneError) ||
          t('settingForm.errorChangePhone'),
        severity: 'error',
      });
    }
  }, [changePhoneError, toast, t]);

  const apiError = useMemo(
    () => sendCodeError || confirmError || changePhoneError,
    [sendCodeError, confirmError, changePhoneError],
  );

  const getErrorMessage = (error: unknown): string | undefined => {
    if (!error) return undefined;
    if (error instanceof Error) return error.message;
    return String(error);
  };

  const isPhoneValid = (code: string, phone: string) => {
    const phoneNum = parsePhoneNumberFromString(code + phone);
    return phoneNum?.isValid();
  };

  const handleBlur = () => {
    setTouched(true);
    if (!phoneNumber) {
      setFormError(t('settingForm.thisFieldIsRequired'));
      return;
    }
    if (!isPhoneValid(countryCode, phoneNumber)) {
      setFormError(t('settingForm.phoneNumberIsInvalid'));
    } else {
      setFormError(undefined);
    }
  };

  const toggleEdit = () => {
    setIsEditing((prev) => {
      if (!prev) {
        setPhoneNumber('');
        setVerificationCode('');
        setIsVerified(false);
        setButtonState('default');
        setShowToast(false);
        setFormError(undefined);
        setTouched(false);
      }
      return !prev;
    });
  };

  const handleSendCode = () => {
    handleBlur();
    if (formError || !isPhoneValid(countryCode, phoneNumber)) return;
    executeSendCode({
      phoneNumber: countryCode + phoneNumber.replace(/^0/, ''),
    });
  };

  const handleVerifyCode = () => {
    if (!verificationCode) {
      setFormError(t('settingForm.verificationCodeRequired'));
      return;
    }
    setFormError(undefined);
    executeConfirmCode({
      phoneNumber: countryCode + phoneNumber.replace(/^0/, ''),
      verifyCode: verificationCode,
    });
  };

  const combinedError = formError || getErrorMessage(apiError);
  const inputError: boolean = touched && !!combinedError;

  return (
    <PageWrapper>
      <CardContainer
        title={t('settingForm.titlePhoneNumber')}
        subtitle={t('settingForm.descriptionPhoneNumber')}
        highlighted={isEditing}
        action={
          <PhoneActionButtons
            isEditing={isEditing}
            toggleEdit={toggleEdit}
            t={t}
          />
        }
      >
        {isLoading ? (
          <Box
            sx={{
              display: 'flex',
              justifyContent: 'center',
              alignItems: 'center',
              p: 4,
              minHeight: '150px',
            }}
          >
            <CircularProgress />
          </Box>
        ) : fetchError ? (
          <Box sx={{ textAlign: 'center', p: 4 }}>
            <Typography color="error">
              {getErrorMessage(fetchError) ||
                t('settingForm.errorFetchPhoneNumber')}
            </Typography>
          </Box>
        ) : isEditing ? (
          <PhoneEditForm
            phoneNumber={phoneNumber}
            setPhoneNumber={setPhoneNumber}
            countryCode={countryCode}
            setCountryCode={setCountryCode}
            verificationCode={verificationCode}
            setVerificationCode={setVerificationCode}
            isVerified={isVerified}
            isVerifying={isVerifying || isSendingCode || isChangingPhone}
            buttonState={buttonState}
            setButtonState={setButtonState}
            handleSendCode={handleSendCode}
            handleVerifyClick={handleVerifyCode}
            error={combinedError}
            inputError={inputError}
            handleBlur={handleBlur}
            textFieldRef={textFieldRef as React.RefObject<HTMLDivElement>}
            inputRef={inputRef as React.RefObject<HTMLInputElement>}
            phones={phones}
            showToast={showToast}
            setShowToast={setShowToast}
            t={t}
          />
        ) : (
          <PhoneDisplay
            phones={phones.map((p) => {
              let localPhone = p.withCode;
              if (localPhone.startsWith('+98')) {
                localPhone = '0' + localPhone.slice(3);
              }
              return {
                ...p,
                phone: toLocaleDigits(localPhone, i18n.language),
              };
            })}
          />
        )}
      </CardContainer>
    </PageWrapper>
  );
}
