import { Errored } from 'dashboard/core/components/errored';
import { Forbidden } from 'dashboard/core/components/forbidden';
import { GrantPermissionsModal } from 'dashboard/core/components/grant-permissions-modal';
import { NotFound } from 'dashboard/core/components/not-found';
import { BannerContext } from 'dashboard/core/contexts/banners';
import { ModalContext } from 'dashboard/core/contexts/modals';
import { useAuthorizedFieldSubscriberGrants } from 'dashboard/core/utils/event-stream';
import { ALL_ENVIRONMENTS } from 'dashboard/definitions/environments';
import { code } from 'dashboard/generated/controlplane';
import { PrefilledGrantData } from 'dashboard/pages/event-manage/components/event-manage-page';
import * as _ from 'lodash';
import * as React from 'react';
import { useContext, useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import {
  AlertBannerType,
  Button,
  ButtonSize,
  ButtonType,
  Color,
  CoreLink,
  CoreText,
  Display,
  JustifyContent,
  Layout,
  LoadingSpinner,
  SVGAsset,
  Table,
  TableCell,
  TableHeader,
  TableHeading,
  TableRow,
  TextAlign,
  TextType,
} from 'twitch-core-ui';

import twirp = code.justin.tv.eventbus.controlplane;

export interface Props {
  eventType: string;
  authorizedFields: twirp.IAuthorizedField[];

  prefilledGrantData?: PrefilledGrantData;
}

export const AuthFieldsSubscriptionTab = ({
  eventType,
  authorizedFields,
  prefilledGrantData,
}: Props) => {
  const {
    authorizedSubscriberDetails: grantsFromAPI,
    loading,
    error,
    forbidden,
    notFound,
    reload,
  } = useAuthorizedFieldSubscriberGrants(eventType);

  const [
    authorizedSubscriberDetails,
    setAuthorizedSubscriberDetails,
  ] = useState<twirp.IGrant[]>(new Array<twirp.IGrant>());
  useEffect(() => {
    setAuthorizedSubscriberDetails(grantsFromAPI);
  }, [grantsFromAPI]);

  const history = useHistory();

  const { showModal } = useContext(ModalContext);
  const { showBanner } = useContext(BannerContext);

  const handleShowGrantSubscriberPermissionModal = (
    et: string,
    environment: string,
  ) => {
    return () =>
      showModal({
        component: GrantPermissionsModal,
        props: {
          prefilledEventType: et,
          prefilledEnvironment: environment,
          subscriberGrant: true,
          authorizedFields,
          onSuccess: () => {
            // Uses the callback provided by useAuthorizedFieldSubscriberGrants
            // to tell it to re-fetch the data
            reload();
          },
        },
      });
  };

  useEffect(() => {
    if (!prefilledGrantData) {
      return;
    }
    showModal({
      component: GrantPermissionsModal,
      props: {
        prefilledEventType: eventType,
        prefilledEnvironment: prefilledGrantData.environment,
        prefilledARN: prefilledGrantData.iamRoleARN,
        prefilledMessageName: prefilledGrantData.messageName,
        prefilledFieldName: prefilledGrantData.fieldName,
        subscriberGrant: true,
        authorizedFields: [
          {
            messageName: prefilledGrantData.messageName,
            fieldName: prefilledGrantData.fieldName,
          },
        ],
        onSuccess: () => {
          // Uses the callback provided by useAuthorizedFieldSubscriberGrants
          // to tell it to re-fetch the data
          reload();
          history.push(`/events/${eventType}/manage`);
          showBanner({
            id: 'sub-grant-success',
            status: 'Success',
            message: 'Authorized field subscriber grant created.',
            type: AlertBannerType.Success,
          });
        },
      },
      onHide: () => history.push(`/events/${eventType}/manage`),
    });
  }, [prefilledGrantData]);

  const subDetailsByEnv = _.groupBy(authorizedSubscriberDetails, 'environment');
  return (
    <>
      {loading && <LoadingSpinner />}
      {error && <Errored text={'Error fetching subscriptions'} />}
      {forbidden && <Forbidden />}
      {notFound && <NotFound />}
      {authorizedFields.length === 0 && (
        <Layout padding={3} textAlign={TextAlign.Center}>
          <CoreText color={Color.Alt2}>
            This event contains no authorized fields. Authorized fields allow
            event owners to grant read access to subscribers explicitly on a
            field by field basis. Read more about authorized fields{' '}
            <CoreLink
              targetBlank
              linkTo="https://git.xarth.tv/pages/eventbus/docs/authorized_fields/"
            >
              here
            </CoreLink>
            .
          </CoreText>
        </Layout>
      )}
      {!loading &&
        !error &&
        !forbidden &&
        !notFound &&
        !(authorizedFields.length === 0) && (
          <Layout padding={0.5}>
            {_.map(ALL_ENVIRONMENTS, (env, i) => {
              return (
                <Layout padding={1} key={i}>
                  <Layout
                    display={Display.Flex}
                    justifyContent={JustifyContent.Between}
                    padding={1}
                  >
                    <CoreText type={TextType.H4}>{_.capitalize(env)}</CoreText>
                    <Button
                      size={ButtonSize.Small}
                      type={ButtonType.Secondary}
                      onClick={handleShowGrantSubscriberPermissionModal(
                        eventType,
                        env,
                      )}
                      icon={SVGAsset.AddReaction}
                    >
                      Add Permission
                    </Button>
                  </Layout>
                  <Table>
                    <TableHeader>
                      <TableHeading
                        label="Message Name"
                        textAlign={TextAlign.Center}
                      />
                      <TableHeading
                        label="Field Name"
                        textAlign={TextAlign.Center}
                      />
                      <TableHeading
                        label="IAM Role"
                        textAlign={TextAlign.Center}
                      />
                      <TableHeading
                        label="Service Name"
                        textAlign={TextAlign.Center}
                      />
                    </TableHeader>
                    {_.size(subDetailsByEnv[env]) === 0 ? (
                      <TableRow>
                        <td colSpan={4}>
                          <Layout
                            padding={1}
                            justifyContent={JustifyContent.Center}
                            display={Display.Flex}
                            fullWidth
                          >
                            <CoreText type={TextType.P} color={Color.Alt2}>
                              There are no authorized field subscribers for this
                              environment.{' '}
                              <CoreLink
                                linkTo={
                                  'http://git.xarth.tv/pages/eventbus/docs/subscribers/authorized_fields/'
                                }
                              >
                                Learn more
                              </CoreLink>
                            </CoreText>
                          </Layout>
                        </td>
                      </TableRow>
                    ) : (
                      _.map(subDetailsByEnv[env], (grant, j) => {
                        return (
                          <TableRow key={j}>
                            <TableCell textAlign={TextAlign.Center}>
                              {grant.messageName}
                            </TableCell>
                            <TableCell textAlign={TextAlign.Center}>
                              {grant.fieldName}
                            </TableCell>
                            <TableCell textAlign={TextAlign.Center}>
                              {grant.iamRoleArn}
                            </TableCell>
                            <TableCell textAlign={TextAlign.Center}>
                              {grant.serviceName}
                            </TableCell>
                          </TableRow>
                        );
                      })
                    )}
                  </Table>
                </Layout>
              );
            })}
          </Layout>
        )}
    </>
  );
};
