import { useEffect, useState } from 'react';

import type { FC } from 'react';

import ErrorText from '~/src/components/ErrorText';
import Loading from '~/src/components/Loading';
import useFetchAccounts from '~/src/hooks/useFetchAccounts';
import { localStorageGet, localStorageSet } from '~/src/lib/utils/localStorage';
import { ACCOUNT_STORAGE } from '../../constants';
import { AccountProvider } from '../../useAccount';
import { Accounts } from './Accounts';

interface UserAccountsProps {
  userId: number;
}

export const UserAccounts: FC<UserAccountsProps> = ({ userId }) => {
  const [accountId, setAccountId] = useState<number | undefined>(
    resolveAccountId(userId)
  );

  const {
    result: accounts,
    isLoading: accountsIsLoading,
    error: accountsError,
  } = useFetchAccounts({ userId }, [userId]);

  useEffect(() => {
    const accountStorage = parseAccountStorage();

    if (accountId !== undefined && accountStorage?.accountId !== accountId) {
      // persist accountId in localStorage to be able to return to the same account
      // when user navigates to another page and back to account page
      localStorageSet(ACCOUNT_STORAGE, `${userId}:${accountId}`);
    }
  }, [accountId, userId]);

  if (accountsIsLoading) {
    return <Loading margin="4rem" />;
  }

  if (accountsError || !accounts || !accounts.length) {
    return (
      <ErrorText
        centered
        error={accountsError ?? new Error('No account found')}
      />
    );
  }

  // covers case when account persisted in local storage
  // no longer exists in the user accounts list (user does not have access anymore)
  const accountIdToFetch = accounts?.some(({ id }) => id === accountId)
    ? accountId
    : accounts?.[0]?.id;

  return (
    <AccountProvider accountId={accountIdToFetch}>
      <Accounts accounts={accounts} updateAccountId={setAccountId} />
    </AccountProvider>
  );
};

const parseAccountStorage = () => {
  const storageAccountData = localStorageGet(ACCOUNT_STORAGE);

  if (!storageAccountData) return;

  const [storageUserId, storageAccountId] = storageAccountData.split(':');

  const userId = parseInt(storageUserId, 10);
  const accountId = parseInt(storageAccountId, 10);

  if (isNaN(userId) || isNaN(accountId)) return;

  return { userId, accountId };
};

const resolveAccountId = (userId: number): number | undefined => {
  const accountStorage = parseAccountStorage();

  let storageAccountId: number | undefined = accountStorage?.accountId;

  // do not use storage if user is different
  if (accountStorage && accountStorage.userId !== userId) {
    storageAccountId = undefined;
  }

  return storageAccountId;
};
