import {Fragment, useCallback, useState} from 'react';

import {LinkButton} from 'sentry/components/button';
import EmptyMessage from 'sentry/components/emptyMessage';
import ExternalLink from 'sentry/components/links/externalLink';
import Link from 'sentry/components/links/link';
import LoadingError from 'sentry/components/loadingError';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import Panel from 'sentry/components/panels/panel';
import PanelAlert from 'sentry/components/panels/panelAlert';
import PanelBody from 'sentry/components/panels/panelBody';
import PanelHeader from 'sentry/components/panels/panelHeader';
import {t, tct} from 'sentry/locale';
import type {Organization} from 'sentry/types/organization';
import type {Project, ProjectKey} from 'sentry/types/project';
import {useApiQuery} from 'sentry/utils/queryClient';
import useOrganization from 'sentry/utils/useOrganization';
import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
import TextBlock from 'sentry/views/settings/components/text/textBlock';
import {LoaderSettings} from 'sentry/views/settings/project/projectKeys/details/loaderSettings';

export function ProjectLoaderScript({project}: {project: Project}) {
  const organization = useOrganization();
  const apiEndpoint = `/projects/${organization.slug}/${project.slug}/keys/`;
  const [updatedProjectKeys, setUpdatedProjectKeys] = useState<ProjectKey[]>([]);

  const {
    data: projectKeys,
    isPending,
    error,
    refetch: refetchProjectKeys,
  } = useApiQuery<ProjectKey[]>([apiEndpoint], {
    staleTime: 0,
  });

  const handleUpdateProjectKey = useCallback(
    (projectKey: ProjectKey) => {
      const existingProjectIndex = updatedProjectKeys.findIndex(
        key => key.id === projectKey.id
      );
      const newUpdatedProjectKeys =
        existingProjectIndex > -1
          ? [...updatedProjectKeys].map((updatedProjectKey, index) => {
              return index === existingProjectIndex ? projectKey : updatedProjectKey;
            })
          : [...updatedProjectKeys, projectKey];

      setUpdatedProjectKeys(newUpdatedProjectKeys);
    },
    [updatedProjectKeys]
  );

  return (
    <Fragment>
      <SettingsPageHeader title={t('Loader Script')} />

      <TextBlock>
        {tct(
          'The Loader Script is the easiest way to initialize the Sentry SDK. The Loader Script automatically keeps your Sentry SDK up to date and offers configuration for different Sentry features. [docsLink:Learn more about the Loader Script]. Note: The Loader Script is bound to a Client Key (DSN), to create a new Script, go to the [clientKeysLink:Client Keys page].',
          {
            docsLink: (
              <ExternalLink href="https://docs.sentry.io/platforms/javascript/install/loader/" />
            ),
            clientKeysLink: (
              <Link
                to={`/settings/${organization.slug}/projects/${project.slug}/keys/`}
              />
            ),
          }
        )}
      </TextBlock>

      {isPending && <LoadingIndicator />}
      {!!error && (
        <LoadingError
          message={t('Failed to load project keys.')}
          onRetry={refetchProjectKeys}
        />
      )}
      {!isPending && !error && !projectKeys?.length && (
        <EmptyMessage title={t('There are no keys active for this project.')} />
      )}

      {projectKeys?.map(key => {
        const actualKey =
          updatedProjectKeys.find(updatedKey => updatedKey.id === key.id) ?? key;
        return (
          <LoaderItem
            key={actualKey.id}
            organization={organization}
            project={project}
            projectKey={actualKey}
            onUpdateProjectKey={handleUpdateProjectKey}
          />
        );
      })}
    </Fragment>
  );
}

function LoaderItem({
  organization,
  project,
  projectKey,
  onUpdateProjectKey,
}: {
  onUpdateProjectKey: (projectKey: ProjectKey) => void;
  organization: Organization;
  project: Project;
  projectKey: ProjectKey;
}) {
  return (
    <Panel>
      <PanelHeader hasButtons>
        {tct('Client Key: [name]', {name: projectKey.name})}

        <LinkButton
          size="xs"
          to={`/settings/${organization.slug}/projects/${project.slug}/keys/${projectKey.id}/`}
        >
          {t('View Key Details')}
        </LinkButton>
      </PanelHeader>
      <PanelBody>
        <PanelAlert type="info" showIcon>
          {t('Note that it can take a few minutes until changed options are live.')}
        </PanelAlert>

        <LoaderSettings
          orgSlug={organization.slug}
          keyId={projectKey.id}
          project={project}
          data={projectKey}
          updateData={onUpdateProjectKey}
        />
      </PanelBody>
    </Panel>
  );
}

export default ProjectLoaderScript;
