import ExternalLink from 'sentry/components/links/externalLink';
import LoadingError from 'sentry/components/loadingError';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import Panel from 'sentry/components/panels/panel';
import PanelBody from 'sentry/components/panels/panelBody';
import PanelHeader from 'sentry/components/panels/panelHeader';
import PreviewFeature from 'sentry/components/previewFeature';
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
import {t, tct} from 'sentry/locale';
import type {ProjectKey} from 'sentry/types/project';
import {useApiQuery} from 'sentry/utils/queryClient';
import routeTitleGen from 'sentry/utils/routeTitle';
import useOrganization from 'sentry/utils/useOrganization';
import {useParams} from 'sentry/utils/useParams';
import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
import ReportUri, {
  getSecurityDsn,
} from 'sentry/views/settings/projectSecurityHeaders/reportUri';

function getInstructions(keyList: ProjectKey[]) {
  return (
    'def middleware(request, response):\n' +
    "    response['Public-Key-Pins'] = \\\n" +
    '        \'pin-sha256="cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs="; \' \\\n' +
    '        \'pin-sha256="M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE="; \' \\\n' +
    "        'max-age=5184000; includeSubDomains; ' \\\n" +
    `        \'report-uri="${getSecurityDsn(keyList)}"\' \n` +
    '    return response\n'
  );
}

function getReportOnlyInstructions(keyList: ProjectKey[]) {
  return (
    'def middleware(request, response):\n' +
    "    response['Public-Key-Pins-Report-Only'] = \\\n" +
    '        \'pin-sha256="cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs="; \' \\\n' +
    '        \'pin-sha256="M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE="; \' \\\n' +
    "        'max-age=5184000; includeSubDomains; ' \\\n" +
    `        \'report-uri="${getSecurityDsn(keyList)}"\' \n` +
    '    return response\n'
  );
}

function ProjectHpkpReports() {
  const organization = useOrganization();
  const {projectId} = useParams();

  const {
    data: keyList,
    isLoading,
    isError,
    refetch,
  } = useApiQuery<ProjectKey[]>([`/projects/${organization.slug}/${projectId}/keys/`], {
    staleTime: 0,
  });

  if (isLoading) {
    return <LoadingIndicator />;
  }

  if (isError) {
    return <LoadingError onRetry={refetch} />;
  }

  return (
    <div>
      <SentryDocumentTitle
        title={routeTitleGen(t('HTTP Public Key Pinning (HPKP)'), projectId, false)}
      />
      <SettingsPageHeader title={t('HTTP Public Key Pinning')} />

      <PreviewFeature />

      <ReportUri keyList={keyList} orgId={organization.slug} projectId={projectId} />

      <Panel>
        <PanelHeader>{t('About')}</PanelHeader>

        <PanelBody withPadding>
          <p>
            {tct(
              `[link:HTTP Public Key Pinning]
              (HPKP) is a security feature that tells a web client to associate a specific
              cryptographic public key with a certain web server to decrease the risk of MITM
              attacks with forged certificates. It's enforced by browser vendors, and Sentry
              supports capturing violations using the standard reporting hooks.`,
              {
                link: (
                  <ExternalLink href="https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning" />
                ),
              }
            )}
          </p>

          <p>
            {t(
              `To configure HPKP reports
              in Sentry, you'll need to send a header from your server describing your
              policy, as well specifying the authenticated Sentry endpoint.`
            )}
          </p>

          <p>
            {t(
              'For example, in Python you might achieve this via a simple web middleware'
            )}
          </p>
          <pre>{getInstructions(keyList)}</pre>

          <p>
            {t(`Alternatively you can setup HPKP reports to simply send reports rather than
              actually enforcing the policy`)}
          </p>
          <pre>{getReportOnlyInstructions(keyList)}</pre>

          <p>
            {tct(
              `We recommend setting this up to only run on a percentage of requests, as
              otherwise you may find that you've quickly exhausted your quota. For more
              information, take a look at [link:the documentation on MDN].`,
              {
                link: (
                  <ExternalLink href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Public_Key_Pinning" />
                ),
              }
            )}
          </p>
        </PanelBody>
      </Panel>
    </div>
  );
}

export default ProjectHpkpReports;