import { Button, Flex, Heading, Image, Link, Text } from '@invoke-ai/ui-library';
import { createSelector } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store/storeHooks';
import { useClipboard } from 'common/hooks/useClipboard';
import { selectConfigSlice } from 'features/system/store/configSlice';
import { toast } from 'features/toast/toast';
import newGithubIssueUrl from 'new-github-issue-url';
import InvokeLogoYellow from 'public/assets/images/invoke-symbol-ylw-lrg.svg';
import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { PiArrowCounterClockwiseBold, PiArrowSquareOutBold, PiCopyBold } from 'react-icons/pi';
import { serializeError } from 'serialize-error';

type Props = {
  error: Error;
  resetErrorBoundary: () => void;
};

const selectIsLocal = createSelector(selectConfigSlice, (config) => config.isLocal);

const AppErrorBoundaryFallback = ({ error, resetErrorBoundary }: Props) => {
  const { t } = useTranslation();
  const isLocal = useAppSelector(selectIsLocal);
  const clipboard = useClipboard();

  const handleCopy = useCallback(() => {
    const text = JSON.stringify(serializeError(error), null, 2);
    clipboard.writeText(`\`\`\`\n${text}\n\`\`\``, () => {
      toast({
        id: 'ERROR_COPIED',
        title: t('toast.errorCopied'),
      });
    });
  }, [clipboard, error, t]);

  const url = useMemo(() => {
    if (isLocal) {
      return newGithubIssueUrl({
        user: 'invoke-ai',
        repo: 'InvokeAI',
        template: 'BUG_REPORT.yml',
        title: `[bug]: ${error.name}: ${error.message}`,
      });
    } else {
      return 'https://support.invoke.ai/support/tickets/new';
    }
  }, [error.message, error.name, isLocal]);

  return (
    <Flex layerStyle="body" w="100dvw" h="100dvh" alignItems="center" justifyContent="center" p={4}>
      <Flex layerStyle="first" flexDir="column" borderRadius="base" justifyContent="center" gap={8} p={16}>
        <Flex alignItems="center" gap="2">
          <Image src={InvokeLogoYellow} alt="invoke-logo" w="24px" h="24px" minW="24px" minH="24px" userSelect="none" />
          <Heading fontSize="2xl">{t('common.somethingWentWrong')}</Heading>
        </Flex>

        <Flex
          layerStyle="second"
          px={8}
          py={4}
          gap={4}
          borderRadius="base"
          justifyContent="space-between"
          alignItems="center"
        >
          <Text fontWeight="semibold" color="error.400">
            {error.name}: {error.message}
          </Text>
        </Flex>
        <Flex gap={4}>
          <Button leftIcon={<PiArrowCounterClockwiseBold />} onClick={resetErrorBoundary}>
            {t('accessibility.resetUI')}
          </Button>
          <Button leftIcon={<PiCopyBold />} onClick={handleCopy}>
            {t('common.copyError')}
          </Button>
          <Link href={url} isExternal>
            <Button leftIcon={<PiArrowSquareOutBold />}>
              {isLocal ? t('accessibility.createIssue') : t('accessibility.submitSupportTicket')}
            </Button>
          </Link>
        </Flex>
      </Flex>
    </Flex>
  );
};

export default memo(AppErrorBoundaryFallback);
