import { useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { useModule, useStatus } from '~/lib/react';
import { useAppDispatch } from '~/store';
import apiReducer, { modules } from '~/store/api/reducer';
import { checkTwitchKeys } from '~/lib/twitch';
import BrowserLink from '../../components/BrowserLink';
import DefinitionTable from '../../components/DefinitionTable';
import RevealLink from '../../components/utils/RevealLink';
import SaveButton from '../../components/forms/SaveButton';
import {
  Button,
  ButtonGroup,
  Field,
  InputBox,
  Label,
  PasswordInputBox,
  SectionHeader,
  styled,
  TextBlock,
} from '../../theme';
import AlertContent from '../../components/AlertContent';
import { Alert } from '../../theme/alert';

const StepList = styled('ul', {
  lineHeight: '1.5',
  listStyleType: 'none',
  listStylePosition: 'outside',
});
const Step = styled('li', {
  marginBottom: '0.5rem',
  paddingLeft: '1rem',
  '&::marker': {
    color: '$teal11',
    content: '▧',
    display: 'inline-block',
    marginLeft: '-0.5rem',
  },
});

type TestResult = { open: boolean; error?: Error };

export default function TwitchAPISettings() {
  const { t } = useTranslation();
  const [httpConfig] = useModule(modules.httpConfig);
  const [twitchConfig, setTwitchConfig, loadStatus] = useModule(
    modules.twitchConfig,
  );
  const status = useStatus(loadStatus.save);
  const dispatch = useAppDispatch();
  const [revealClientSecret, setRevealClientSecret] = useState(false);
  const [testing, setTesting] = useState(false);
  const [testResult, setTestResult] = useState<TestResult>({
    open: false,
  });

  const checkCredentials = async () => {
    setTesting(true);
    if (twitchConfig) {
      try {
        await checkTwitchKeys(
          twitchConfig.api_client_id,
          twitchConfig.api_client_secret,
        );
        setTestResult({ open: true });
      } catch (e: unknown) {
        setTestResult({ open: true, error: e as Error });
      }
    }
    setTesting(false);
  };

  return (
    <form
      onSubmit={(ev) => {
        void dispatch(setTwitchConfig(twitchConfig));
        ev.preventDefault();
      }}
    >
      <SectionHeader spacing={'none'}>
        {t('pages.twitch-settings.api-subheader')}
      </SectionHeader>
      <TextBlock>{t('pages.twitch-settings.apiguide-1')}</TextBlock>
      <StepList>
        <Step>
          <Trans i18nKey="pages.twitch-settings.apiguide-2">
            {' '}
            <BrowserLink href="https://dev.twitch.tv/console/apps/create">
              https://dev.twitch.tv/console/apps/create
            </BrowserLink>
          </Trans>
        </Step>
        <Step>
          {t('pages.twitch-settings.apiguide-3')}

          <DefinitionTable
            entries={{
              [t('pages.twitch-settings.app-oauth-redirect-url')]: `http://${
                httpConfig?.bind.indexOf(':') > 0
                  ? httpConfig.bind
                  : `localhost${httpConfig?.bind ?? ':4337'}`
              }/twitch/callback`,
              [t('pages.twitch-settings.app-category')]: 'Broadcasting Suite',
            }}
          />
        </Step>
        <Step>
          <Trans i18nKey="pages.twitch-settings.apiguide-4">
            {'str1 '}
            <b>str2</b>
          </Trans>
        </Step>
      </StepList>
      <Field size="fullWidth" css={{ marginTop: '2rem' }}>
        <Label htmlFor="clientid">
          {t('pages.twitch-settings.app-client-id')}
        </Label>
        <InputBox
          type="text"
          id="clientid"
          placeholder={t('pages.twitch-settings.app-client-id')}
          required={true}
          value={twitchConfig?.api_client_id ?? ''}
          onChange={(ev) =>
            dispatch(
              apiReducer.actions.twitchConfigChanged({
                ...twitchConfig,
                api_client_id: ev.target.value,
              }),
            )
          }
        />
      </Field>

      <Field size="fullWidth">
        <Label htmlFor="clientsecret">
          {t('pages.twitch-settings.app-client-secret')}
          <RevealLink
            value={revealClientSecret}
            setter={setRevealClientSecret}
          />
        </Label>
        <PasswordInputBox
          reveal={revealClientSecret}
          id="clientsecret"
          placeholder={t('pages.twitch-settings.app-client-secret')}
          required={true}
          value={twitchConfig?.api_client_secret ?? ''}
          onChange={(ev) =>
            dispatch(
              apiReducer.actions.twitchConfigChanged({
                ...twitchConfig,
                api_client_secret: ev.target.value,
              }),
            )
          }
        />
      </Field>
      <ButtonGroup>
        <SaveButton status={status} />
        <Button
          type="button"
          onClick={() => {
            void checkCredentials();
          }}
          disabled={testing}
        >
          {t('pages.twitch-settings.test-button')}
        </Button>
      </ButtonGroup>
      <Alert
        defaultOpen={false}
        open={testResult.open}
        onOpenChange={(val: boolean) => {
          setTestResult({ ...testResult, open: val });
        }}
      >
        <AlertContent
          variation={testResult.error ? 'danger' : 'default'}
          description={
            testResult.error
              ? t('pages.twitch-settings.test-failed', {
                  error: testResult.error.message,
                })
              : t('pages.twitch-settings.test-succeeded')
          }
          actionText={t('form-actions.ok')}
          onAction={() => {
            setTestResult({ ...testResult, open: false });
          }}
        />
      </Alert>
    </form>
  );
}
