import {Fragment} from 'react';

import ExternalLink from 'sentry/components/links/externalLink';
import List from 'sentry/components/list/';
import ListItem from 'sentry/components/list/listItem';
import {Layout, LayoutProps} from 'sentry/components/onboarding/gettingStartedDoc/layout';
import {ModuleProps} from 'sentry/components/onboarding/gettingStartedDoc/sdkDocumentation';
import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
import {t, tct} from 'sentry/locale';

// Configuration Start
export const steps = ({
  dsn,
}: Partial<Pick<ModuleProps, 'dsn'>> = {}): LayoutProps['steps'] => [
  {
    type: StepType.INSTALL,
    description: (
      <p>
        {tct(
          'Sentry captures data by using an SDK within your application’s runtime. If you are using Expo, see [expoLink:How to Add Sentry to Your Expo Project]. This SDK works for both managed and bare projects.',
          {expoLink: <ExternalLink href="https://docs.expo.dev/guides/using-sentry/" />}
        )}
      </p>
    ),
    configurations: [
      {
        language: 'bash',
        description: <div>{tct('Run [code:@sentry/wizard]:', {code: <code />})}</div>,
        code: 'npx @sentry/wizard@latest -s -i reactNative',
        additionalInfo: (
          <Fragment>
            <p>
              {tct(
                '[wizardLink:Sentry Wizard] will patch your project accordingly, though you can [setupManuallyLink:setup manually] if you prefer.',
                {
                  wizardLink: (
                    <ExternalLink href="https://github.com/getsentry/sentry-wizard" />
                  ),
                  setupManuallyLink: (
                    <ExternalLink href="https://docs.sentry.io/platforms/react-native/manual-setup/manual-setup/" />
                  ),
                }
              )}
            </p>
            <List symbol="bullet">
              <ListItem>
                {t(
                  'iOS Specifics: When you use Xcode, you can hook directly into the build process to upload debug symbols and source maps.'
                )}
              </ListItem>
              <ListItem>
                {tct(
                  "Android Specifics: We hook into Gradle for the source map build process. When you run [gradLewCode:./gradlew] assembleRelease, source maps are automatically built and uploaded to Sentry. If you have enabled Gradle's [orgGradleCode:org.gradle.configureondemand] feature, you'll need a clean build, or you'll need to disable this feature to upload the source map on every build by setting [orgGradleCodeConfigureCode:org.gradle.configureondemand=false] or remove it.",
                  {
                    gradLewCode: <code />,
                    orgGradleCode: <code />,
                    orgGradleCodeConfigureCode: <code />,
                  }
                )}
              </ListItem>
            </List>
          </Fragment>
        ),
      },
    ],
  },
  {
    type: StepType.CONFIGURE,
    configurations: [
      {
        language: 'javascript',
        code: `
        import * as Sentry from "@sentry/react-native";

        Sentry.init({
          dsn: "${dsn}",
          // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
          // We recommend adjusting this value in production.
          tracesSampleRate: 1.0,
        });
        `,
        additionalInfo: (
          <p>
            {tct('The "sentry-wizard" will try to add it to your [code:App.tsx]', {
              code: <code />,
            })}
          </p>
        ),
      },
      {
        language: 'javascript',
        description: (
          <p>
            {tct(
              'Wrap your app with Sentry to automatically instrument it with [touchEventTrakingLink:touch event tracking] and [automaticPerformanceMonitoringLink:automatic performance monitoring]:',
              {
                touchEventTrakingLink: (
                  <ExternalLink href="https://docs.sentry.io/platforms/react-native/touchevents/" />
                ),
                automaticPerformanceMonitoringLink: (
                  <ExternalLink href="https://docs.sentry.io/platforms/react-native/performance/instrumentation/automatic-instrumentation/" />
                ),
              }
            )}
          </p>
        ),
        code: 'export default Sentry.wrap(App);',
        additionalInfo: t(
          'You do not need to do this for Sentry to work or if your app does not have a single parent "App" component.'
        ),
      },
    ],
  },
  {
    type: StepType.VERIFY,
    description: t(
      'Then create an intentional error, so you can test that everything is working:'
    ),
    configurations: [
      {
        language: 'javascript',
        code: "throw new Error('My first Sentry error!');",
      },
      {
        language: 'javascript',
        description: t('Or, try a native crash with:'),
        code: 'Sentry.nativeCrash();',
        additionalInfo: (
          <Fragment>
            {t(
              "If you're new to Sentry, use the email alert to access your account and complete a product tour."
            )}
            {t(
              "If you're an existing user and have disabled alerts, you won't receive this email."
            )}
          </Fragment>
        ),
      },
    ],
  },
  {
    title: t('Performance'),
    description: (
      <Fragment>
        {t(
          'Sentry can measure the performance of your app automatically when instrumented with the following routers:'
        )}
        <List symbol="bullet">
          <ListItem>
            <ExternalLink href="https://docs.sentry.io/platforms/react-native/performance/instrumentation/automatic-instrumentation/#react-navigation">
              {t('React Navigation')}
            </ExternalLink>
          </ListItem>
          <ListItem>
            <ExternalLink href="https://docs.sentry.io/platforms/react-native/performance/instrumentation/automatic-instrumentation/#react-navigation-v4">
              {t('React Navigation V4 and prior')}
            </ExternalLink>
          </ListItem>
          <ListItem>
            <ExternalLink href="https://docs.sentry.io/platforms/react-native/performance/instrumentation/automatic-instrumentation/#react-native-navigation">
              {t('React Native Navigation')}
            </ExternalLink>
          </ListItem>
        </List>
        {t('Additionally, you can create transactions and spans programatically:')}
      </Fragment>
    ),
    configurations: [
      {
        description: t('For example:'),
        language: 'javascript',
        code: `
        // Let's say this function is invoked when a user clicks on the checkout button of your shop
        shopCheckout() {
          // This will create a new Transaction for you
          const transaction = Sentry.startTransaction({ name: "shopCheckout" });
          // Set transaction on scope to associate with errors and get included span instrumentation
          // If there's currently an unfinished transaction, it may be dropped
          Sentry.getCurrentHub().configureScope(scope => scope.setSpan(transaction));

          // Assume this function makes an xhr/fetch call
          const result = validateShoppingCartOnServer();

          const span = transaction.startChild({
            data: {
              result
            },
            op: 'task',
            description: "processing shopping cart result",
          });
          try {
            processAndValidateShoppingCart(result);
            span.setStatus(SpanStatus.Ok);
          } catch (err) {
            span.setStatus(SpanStatus.UnknownError);
            throw err;
          } finally {
            span.finish();
            transaction.finish();
          }
        }
        `,
        additionalInfo: (
          <p>
            {tct(
              'For more information, please refer to the [docLink: Sentry React Native documentation].',
              {
                docLink: (
                  <ExternalLink href="https://docs.sentry.io/platforms/react-native/performance/instrumentation/" />
                ),
              }
            )}
          </p>
        ),
      },
    ],
  },
  {
    title: t('Debug Symbols'),
    description: (
      <Fragment>
        {t(
          'We offer a range of methods to provide Sentry with debug symbols so that you can see symbolicated stack traces and triage issues faster.'
        )}
        <p>
          {tct(
            "Complete stack traces will be shown for React Native Javascript errors by default using Sentry's [automaticSourceMapsUploadLink:automatic source maps upload]. To set up manual source maps upload follow [guideLink:this guide].",
            {
              automaticSourceMapsUploadLink: (
                <ExternalLink href="https://docs.sentry.io/platforms/react-native/sourcemaps/" />
              ),
              guideLink: (
                <ExternalLink href="https://docs.sentry.io/platforms/react-native/sourcemaps/" />
              ),
            }
          )}
        </p>
        <p>
          {tct(
            "You'll also need to upload [debugSymbolsLink:Debug Symbols] generated by the native iOS and Android tooling for native crashes.",
            {
              debugSymbolsLink: (
                <ExternalLink href="https://docs.sentry.io/platforms/react-native/upload-debug/" />
              ),
            }
          )}
        </p>
      </Fragment>
    ),
  },
  {
    title: t('Source Context'),
    description: (
      <Fragment>
        <p>
          {tct(
            "If Sentry has access to your application's source code, it can show snippets of code [italic:(source context)] around the location of stack frames, which helps to quickly pinpoint problematic code.",
            {
              italic: <i />,
            }
          )}
        </p>
        <p>
          {tct(
            'Source Context will be shown for React Native Javascript error by default if source maps are uploaded. To set up source maps upload, follow the [sourceMapsGuideLink:Source Maps guide].',
            {
              sourceMapsGuideLink: (
                <ExternalLink href="https://docs.sentry.io/platforms/react-native/sourcemaps/" />
              ),
            }
          )}
        </p>
        <p>
          {tct(
            "To enable source context for native errors, you'll need to upload native debug symbols to Sentry by following the instructions at [uploadWithGradleLink:Uploading Source Code Context With Sentry Gradle Plugin] and Uploading Source Context With Xcode.",
            {
              uploadWithGradleLink: (
                <ExternalLink href="https://docs.sentry.io/platforms/react-native/upload-debug/#uploading-source-context-with-sentry-gradle-plugin" />
              ),
              uploadWithXCodeLink: (
                <ExternalLink href="https://docs.sentry.io/platforms/react-native/upload-debug/#uploading-source-context-with-xcode" />
              ),
            }
          )}
        </p>
      </Fragment>
    ),
  },
];
// Configuration End

export function GettingStartedWithReactNative({dsn, ...props}: ModuleProps) {
  return <Layout steps={steps({dsn})} {...props} />;
}

export default GettingStartedWithReactNative;