import { useCallback, useEffect, useState } from 'react';
import { createRoot } from 'react-dom/client';
import useMount from 'react-use/lib/useMount';
import { SessionIcon, SessionIconProps, SessionIconType } from '../components/icon';
import { sleepFor } from '../session/utils/Promise';
import { useIsDarkTheme } from '../state/selectors/theme';
import { ThemeKeys, getThemeValue } from '../themes/globals';

const chooseIconColors = (
  isThemed: boolean,
  isDarkTheme: boolean,
  darkColor: ThemeKeys,
  lightColor: ThemeKeys,
  fallbackColor: ThemeKeys
) => {
  return getThemeValue(isThemed ? (isDarkTheme ? darkColor : lightColor) : fallbackColor);
};

const convertIconToImageURL = async (
  props: { isThemed: boolean; isDarkTheme: boolean } & Pick<
    SessionIconProps,
    'iconType' | 'iconSize' | 'iconColor' | 'backgroundColor'
  >
): Promise<{ dataUrl: string; bgColor: string; fgColor: string }> => {
  const { isThemed, isDarkTheme, iconType, iconSize, iconColor, backgroundColor } = props;

  let bgColor = backgroundColor;
  let fgColor = iconColor;

  if (!bgColor) {
    bgColor = chooseIconColors(
      isThemed,
      isDarkTheme,
      '--text-primary-color',
      '--background-primary-color',
      '--white-color'
    );
  }

  if (!fgColor) {
    fgColor = chooseIconColors(
      isThemed,
      isDarkTheme,
      '--background-primary-color',
      '--text-primary-color',
      '--black-color'
    );
  }

  const root = document.querySelector('#root');
  const divElement = document.createElement('div');
  divElement.id = 'icon-to-image-url';
  root?.appendChild(divElement);

  const reactRoot = createRoot(divElement!);
  reactRoot.render(
    <SessionIcon
      iconType={iconType}
      iconSize={iconSize}
      iconColor={iconColor}
      backgroundColor={backgroundColor}
    />
  );
  // wait for it to render
  await sleepFor(100);
  const svg = root?.querySelector(`#icon-to-image-url svg`);
  svg?.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
  const svgString = svg?.outerHTML;
  reactRoot?.unmount();
  root?.removeChild(divElement);

  return {
    bgColor,
    fgColor,
    dataUrl: svgString ? `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}` : '',
  };
};

export const useIconToImageURL = ({
  iconType,
  iconSize,
  isThemed = true,
}: {
  iconType: SessionIconType;
  iconSize: number;
  isThemed?: boolean;
}) => {
  const isDarkTheme = useIsDarkTheme();
  const [dataURL, setDataURL] = useState('');
  const [loading, setLoading] = useState(false);
  const [mounted, setMounted] = useState(false);
  const [inDarkTheme, setInDarkTheme] = useState(false);
  const [backgroundColor, setBackgroundColor] = useState('');
  const [iconColor, setIconColor] = useState('');

  const loadURL = useCallback(async () => {
    setLoading(true);
    setDataURL('');

    try {
      const {
        dataUrl: newURL,
        bgColor,
        fgColor,
      } = await convertIconToImageURL({
        isThemed,
        isDarkTheme,
        iconType,
        iconSize,
        iconColor,
        backgroundColor,
      });

      if (!newURL) {
        throw new Error('[useIconToImageURL] Failed to convert icon to URL');
      }

      setBackgroundColor(bgColor);
      setIconColor(fgColor);
      setDataURL(newURL);

      if (!mounted) {
        setMounted(true);
      }
      setLoading(false);
      setInDarkTheme(!!isThemed && isDarkTheme);
    } catch (error) {
      window.log.error('[useIconToImageURL] Error fetching icon data url', error);
    }
  }, [backgroundColor, iconColor, iconSize, iconType, isDarkTheme, isThemed, mounted]);

  useMount(() => {
    void loadURL();
  });

  useEffect(() => {
    if (!loading && mounted && isThemed && isDarkTheme !== inDarkTheme) {
      void loadURL();
    }
  }, [inDarkTheme, isDarkTheme, isThemed, loadURL, loading, mounted]);

  return { dataURL, iconSize, iconColor, backgroundColor, loading };
};
