import { EnvironmentPill } from 'dashboard/core/components/environment-pill';
import { Errored } from 'dashboard/core/components/errored';
import { Forbidden } from 'dashboard/core/components/forbidden';
import { GrantPermissionsModal } from 'dashboard/core/components/grant-permissions-modal';
import { StyledLoadingSpinner } from 'dashboard/core/components/loading-spinner';
import { ModalContext } from 'dashboard/core/contexts/modals';
import { useAuthorizedFieldGrants } from 'dashboard/core/utils/authorized-fields';
import { code } from 'dashboard/generated/controlplane';
import { AddIAMRoleModal } from 'dashboard/pages/service-overview/components/add-iam-role-modal';
import { ConfirmPublishDeleteModal } from 'dashboard/pages/service-overview/components/confirm-publish-delete-modal';
import { DeleteIAMRoleModal } from 'dashboard/pages/service-overview/components/delete-iam-role-modal';
import { EditIAMRoleLabelModal } from 'dashboard/pages/service-overview/components/edit-iam-role-label-modal';
import * as _ from 'lodash';
import * as React from 'react';
import { useContext, useEffect, useState } from 'react';
import {
  AlignItems,
  Background,
  BalloonSize,
  Button,
  ButtonSize,
  ButtonType,
  Color,
  Column,
  CoreButtonSize,
  CoreLink,
  CoreLinkType,
  CoreText,
  Display,
  DropDownMenu,
  DropDownMenuHeading,
  DropDownMenuItem,
  DropDownMenuSeparator,
  FlexDirection,
  FontSize,
  Grid,
  InteractableType,
  JustifyContent,
  Layout,
  SelectButton,
  SVGAsset,
  TableBody,
  TableCell,
  TableRow,
  TextType,
  Title,
  Typeset,
  useDialogState,
} from 'twitch-core-ui';
import { CloudFormationVersion } from './cloudformation';
import { IAMRoleValidation } from './validation';

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

interface Props {
  service: twirp.IService;
  onReloadService: () => void;
}
export const IAMRoles = ({ service, onReloadService }: Props) => {
  const {
    publisherGrants,
    subscriberGrants,
    loading,
    error,
    forbidden,
    reload: reloadGrants,
  } = useAuthorizedFieldGrants(service.id as string);

  const [iamRoles, setIAMRoles] = useState<Array<twirp.IIAMRole>>(
    new Array<twirp.IIAMRole>(),
  );
  useEffect(() => {
    if (!_.isNil(service.iamRoles)) {
      setIAMRoles(service.iamRoles);
    }
  }, [service]);

  const publisherGrantsByARN = _.groupBy(publisherGrants, 'iamRole.arn');
  const subscriberGrantsByARN = _.groupBy(subscriberGrants, 'iamRole.arn');

  const { showModal } = useContext(ModalContext);
  const handleShowAddIAMRoleModal = () => {
    showModal({
      component: AddIAMRoleModal,
      props: {
        serviceID: service.id,
        onSuccess: () => onReloadService(),
      },
    });
  };

  const handleShowGrantPublishPermissionModal = (arn: string) => {
    return () =>
      showModal({
        component: GrantPermissionsModal,
        props: {
          service,
          prefilledARN: arn,
          onSuccess: () => {
            reloadGrants();
          },
        },
      });
  };

  const onDeletePublishGrant = (
    deletedGrant: twirp.IAuthorizedFieldPublisherGrant,
  ) => {
    _.remove(publisherGrants, (publisherGrant) =>
      _.isEqual(publisherGrant, deletedGrant),
    );
  };

  const onDeleteIAMRole = (arn: string) => {
    setIAMRoles(_.filter(iamRoles, (iamRole) => !_.isEqual(iamRole.arn, arn)));
  };

  const onUpdateIAMRoleLabel = (iamRole: twirp.IIAMRole) =>
    setIAMRoles(
      _.sortBy(
        [..._.filter(iamRoles, (i) => i.arn !== iamRole.arn), iamRole],
        'label',
      ),
    );

  if (forbidden) {
    return <Forbidden />;
  } else if (loading) {
    return <StyledLoadingSpinner />;
  } else if (!_.isNil(error)) {
    return <Errored text={'Error fetching IAM roles and permissions'} />;
  } else if (iamRoles.length === 0) {
    return (
      <Layout
        display={Display.Flex}
        justifyContent={JustifyContent.Center}
        alignItems={AlignItems.Center}
      >
        <Layout>
          <CoreText type={TextType.P} color={Color.Alt2}>
            No IAM roles registered for this service. IAM roles are used to
            grant permissions to publishers for sending events and to
            subscribers for decrypting authorized fields.
          </CoreText>
        </Layout>
        <Layout padding={0.5}>
          <Button
            size={ButtonSize.Default}
            onClick={handleShowAddIAMRoleModal}
            icon={SVGAsset.AddReaction}
          >
            Register New IAM Role
          </Button>
        </Layout>
      </Layout>
    );
  }

  return (
    <Grid>
      <Column cols={12} key={'register-button'}>
        <Layout
          display={Display.Flex}
          flexDirection={FlexDirection.RowReverse}
          padding={0.5}
        >
          <Button
            size={ButtonSize.Default}
            onClick={handleShowAddIAMRoleModal}
            icon={SVGAsset.AddReaction}
          >
            Register New IAM Role
          </Button>
        </Layout>
      </Column>
      {_.map(iamRoles, (iamRole, i) => (
        <Column cols={12} key={i}>
          <Layout margin={{ bottom: 1 }} padding={2}>
            <IAMRoleCard
              arn={iamRole.arn as string}
              label={iamRole.label as string}
              publisherGrants={_.get(
                publisherGrantsByARN,
                iamRole.arn!,
                new Array<twirp.IAuthorizedFieldPublisherGrant>(),
              )}
              subscriberGrants={_.get(
                subscriberGrantsByARN,
                iamRole.arn as string,
                new Array<twirp.IAuthorizedFieldSubscriberGrant>(),
              )}
              onDeletePublishGrant={onDeletePublishGrant}
              onShowGrantPublishPermissionModal={handleShowGrantPublishPermissionModal(
                iamRole.arn!,
              )}
              onDeleteIAMRoleSuccess={onDeleteIAMRole}
              onUpdateIAMRoleLabel={onUpdateIAMRoleLabel}
            />
          </Layout>
        </Column>
      ))}
    </Grid>
  );
};

interface CardProps {
  arn: string;
  label: string;
  publisherGrants: twirp.IAuthorizedFieldPublisherGrant[];
  subscriberGrants: twirp.IAuthorizedFieldSubscriberGrant[];
  onDeletePublishGrant: (
    deletedGrant: twirp.IAuthorizedFieldPublisherGrant,
  ) => void;
  onShowGrantPublishPermissionModal: () => void;
  onDeleteIAMRoleSuccess: (arn: string) => void;
  onUpdateIAMRoleLabel: (iamRole: twirp.IIAMRole) => void;
}
const IAMRoleCard = ({
  arn,
  label,
  publisherGrants,
  subscriberGrants,
  onDeletePublishGrant,
  onShowGrantPublishPermissionModal,
  onDeleteIAMRoleSuccess,
  onUpdateIAMRoleLabel,
}: CardProps) => {
  const { showModal } = useContext(ModalContext);

  const { dialogProps, anchorProps } = useDialogState();

  const [publisherEditMode, setPublisherEditMode] = useState(false);
  const handleEnablePublisherEditMode = () => {
    setPublisherEditMode(true);
    dialogProps.onRequestClose();
  };
  const handleDisablePublisherEditMode = () => setPublisherEditMode(false);

  const handleShowEditLabelModal = () => {
    dialogProps.onRequestClose();
    showModal({
      component: EditIAMRoleLabelModal,
      props: {
        iamRole: {
          arn,
          label,
        },
        onSuccess: onUpdateIAMRoleLabel,
      },
    });
  };

  const handleShowDeleteIAMRoleModal = () => {
    dialogProps.onRequestClose();
    showModal({
      component: DeleteIAMRoleModal,
      props: {
        arn,
        onSuccess: onDeleteIAMRoleSuccess,
        isAllowed:
          publisherGrants.length === 0 && subscriberGrants.length === 0,
      },
    });
  };

  return (
    <Layout elevation={2}>
      <Grid>
        <Column cols={12}>
          <Layout display={Display.Flex} padding={1}>
            <Layout flexGrow={1}>
              <Layout
                display={Display.Flex}
                flexDirection={FlexDirection.Row}
                alignItems={AlignItems.Center}
              >
                <Layout>
                  <Title>{label}</Title>
                </Layout>
                <Layout margin={{ x: 0.5 }}>
                  <IAMRoleValidation arn={arn} />
                </Layout>
                <Layout margin={{ x: 0.5 }}>
                  <CloudFormationVersion arn={arn} />
                </Layout>
              </Layout>
              <Layout padding={{ x: 1 }}>
                <CoreText fontSize={FontSize.Size5} color={Color.Alt2}>
                  {arn}
                </CoreText>
              </Layout>
            </Layout>
            <Layout>
              <SelectButton {...anchorProps} size={CoreButtonSize.Small}>
                More
              </SelectButton>
              <DropDownMenu {...dialogProps} size={BalloonSize.Small}>
                <DropDownMenuHeading>IAM Role</DropDownMenuHeading>
                <DropDownMenuItem
                  figure={{ icon: SVGAsset.Edit }}
                  onClick={handleShowEditLabelModal}
                >
                  Change Label
                </DropDownMenuItem>
                <DropDownMenuItem
                  figure={{ icon: SVGAsset.Trash }}
                  type={InteractableType.Alert}
                  onClick={handleShowDeleteIAMRoleModal}
                >
                  Delete
                </DropDownMenuItem>
                <DropDownMenuSeparator />
                <DropDownMenuHeading>Publisher</DropDownMenuHeading>
                <DropDownMenuItem
                  figure={{ icon: SVGAsset.Gear }}
                  onClick={handleEnablePublisherEditMode}
                >
                  Modify Permissions
                </DropDownMenuItem>
              </DropDownMenu>
            </Layout>
          </Layout>
        </Column>

        <Column cols={12}>
          <Layout borderTop>
            <Layout margin={{ x: 1, y: 1 }}>
              <AuthorizedFieldPublisherGrantTable
                publisherGrants={publisherGrants}
                onDelete={onDeletePublishGrant}
                editMode={publisherEditMode}
                onDisableEditMode={handleDisablePublisherEditMode}
                onShowGrantPublishPermissionModal={
                  onShowGrantPublishPermissionModal
                }
              />
            </Layout>
          </Layout>
        </Column>

        <Column cols={12}>
          <Layout borderTop>
            <Layout margin={{ x: 1, y: 1 }}>
              <AuthorizedFieldSubscriberGrantTable
                subscriberGrants={subscriberGrants}
              />
            </Layout>
          </Layout>
        </Column>
      </Grid>
    </Layout>
  );
};

interface AuthorizedFieldPublisherGrantTableProps {
  publisherGrants: twirp.IAuthorizedFieldPublisherGrant[];
  onDelete: (deletedGrant: twirp.IAuthorizedFieldPublisherGrant) => void;
  editMode: boolean;
  onDisableEditMode: () => void;
  onShowGrantPublishPermissionModal: () => void;
}
const AuthorizedFieldPublisherGrantTable = ({
  publisherGrants,
  onDelete,
  editMode,
  onDisableEditMode,
  onShowGrantPublishPermissionModal,
}: AuthorizedFieldPublisherGrantTableProps) => {
  const { showModal } = useContext(ModalContext);

  const handleShowConfirmPublishDeleteModal = (i: number) => {
    showModal({
      component: ConfirmPublishDeleteModal,
      props: {
        publisherGrant: publisherGrants[i],
        onSuccess: (deletedGrant: twirp.IAuthorizedFieldPublisherGrant) => {
          onDelete(deletedGrant);
        },
      },
    });
  };

  return (
    <Layout>
      <Layout display={Display.Flex} flexDirection={FlexDirection.Row}>
        <Layout flexGrow={1}>
          <CoreText fontSize={FontSize.Size5} bold>
            Publisher Permissions
          </CoreText>
        </Layout>
        {editMode && (
          <>
            <Layout margin={{ x: 0.5 }}>
              <Button
                size={ButtonSize.Small}
                type={ButtonType.Secondary}
                onClick={onShowGrantPublishPermissionModal}
              >
                Add Permission
              </Button>
            </Layout>
            <Layout margin={{ x: 0.5 }}>
              <Button
                size={ButtonSize.Small}
                type={ButtonType.Success}
                icon={SVGAsset.Check}
                onClick={onDisableEditMode}
              />
            </Layout>
          </>
        )}
      </Layout>
      <Layout margin={{ x: 1 }}>
        <table>
          <TableBody>
            {_.map(publisherGrants, (grant, i) => (
              <TableRow key={i}>
                {editMode && (
                  <TableCell>
                    <Button
                      type={ButtonType.Alert}
                      icon={SVGAsset.Trash}
                      size={ButtonSize.Small}
                      onClick={handleShowConfirmPublishDeleteModal.bind(
                        null,
                        i,
                      )}
                    />
                  </TableCell>
                )}
                <TableCell>
                  <EnvironmentPill environment={grant.environment!} />
                </TableCell>
                <TableCell>
                  <CoreLink
                    linkTo={`/events/${grant.eventType}`}
                    type={CoreLinkType.Inherit}
                    targetBlank
                  >
                    <CoreText fontSize={FontSize.Size7}>
                      {grant.eventType}
                    </CoreText>
                  </CoreLink>
                </TableCell>
              </TableRow>
            ))}
          </TableBody>
        </table>
        {publisherGrants.length === 0 && (
          <Layout padding={1} display={Display.Flex} fullWidth>
            <CoreText fontSize={FontSize.Size8} color={Color.Alt2}>
              This IAM role has no permissions to publish to any event streams.{' '}
              <CoreLink linkTo="https://git.xarth.tv/pages/eventbus/docs/publishers/">
                Learn more
              </CoreLink>
            </CoreText>
          </Layout>
        )}
      </Layout>
    </Layout>
  );
};

interface AuthorizedFieldSubscriberGrantTableProps {
  subscriberGrants: twirp.IAuthorizedFieldSubscriberGrant[];
}
const AuthorizedFieldSubscriberGrantTable = ({
  subscriberGrants,
}: AuthorizedFieldSubscriberGrantTableProps) => {
  return (
    <Layout>
      <Layout display={Display.Flex} flexDirection={FlexDirection.Row}>
        <Layout flexGrow={1}>
          <CoreText fontSize={FontSize.Size5} bold>
            Subscriber Permissions
          </CoreText>
        </Layout>
      </Layout>
      <Layout margin={{ x: 1 }}>
        <table>
          <TableBody>
            {_.map(subscriberGrants, (grant, i) => (
              <TableRow key={i}>
                <TableCell>
                  <EnvironmentPill environment={grant.environment!} />
                </TableCell>
                <TableCell>
                  <CoreLink
                    linkTo={`/events/${grant.eventType}`}
                    type={CoreLinkType.Inherit}
                    targetBlank
                  >
                    <CoreText fontSize={FontSize.Size7}>
                      {grant.eventType}
                    </CoreText>
                  </CoreLink>
                </TableCell>
                <TableCell>
                  <Layout padding={{ x: 0.5 }} background={Background.Alt}>
                    <Typeset baseFontSize={FontSize.Size8}>
                      <code>
                        {grant.authorizedField?.messageName} /{' '}
                        {grant.authorizedField?.fieldName}
                      </code>
                    </Typeset>
                  </Layout>
                </TableCell>
              </TableRow>
            ))}
          </TableBody>
        </table>
        {subscriberGrants.length === 0 && (
          <Layout padding={1} display={Display.Flex} fullWidth>
            <CoreText fontSize={FontSize.Size8} color={Color.Alt2}>
              This IAM role has no permissions to decrypt authorized fields.{' '}
              <CoreLink
                linkTo={
                  'http://git.xarth.tv/pages/eventbus/docs/subscribers/authorized_fields/'
                }
              >
                Learn more
              </CoreLink>
            </CoreText>
          </Layout>
        )}
      </Layout>
    </Layout>
  );
};

// return (
//   <Layout margin={{ bottom: 2 }}>
//     <Table className="permission-table">
//       <TableHeader>
//         <TableHeading label="Event Type" textAlign={TextAlign.Center} />
//         <TableHeading label="Environment" textAlign={TextAlign.Center} />
//         <TableHeading label="" textAlign={TextAlign.Center} />
//         <TableHeading label="" textAlign={TextAlign.Center} />
//       </TableHeader>
//       {_.map(publisherGrants, (grant, i) => {
//         return (
//           <TableRow key={i}>
//             <TableCell
//               textAlign={TextAlign.Center}
//               className="permission-table-cell"
//             >
//               {grant.eventType}
//             </TableCell>
//             <TableCell
//               textAlign={TextAlign.Center}
//               className="permission-table-cell"
//             >
//               {grant.environment}
//             </TableCell>
//             <TableCell
//               textAlign={TextAlign.Center}
//               className="permission-table-cell"
//             />
//             <TableCell
//               textAlign={TextAlign.Center}
//               className="permission-table-cell"
//             >
//               <Button
//                 type={ButtonType.Secondary}
//                 onClick={handleShowConfirmPublishDeleteModal.bind(null, i)}
//               >
//                 {/* <ButtonIcon
//                   icon={SVGAsset.Trash}
//                   size={ButtonIconSize.Small}
//                 /> */}
//               </Button>
//             </TableCell>
//           </TableRow>
//         );
//       })}
//       {publisherGrants.length === 0 && (
//         <TableRow>
//           <td colSpan={4}>
// <Layout
//   padding={1}
//   justifyContent={JustifyContent.Center}
//   display={Display.Flex}
//   fullWidth
// >
//   <CoreText type={TextType.P} color={Color.Alt2}>
//     This service is not authorized to publish to any event
//     streams.{' '}
//     <CoreLink linkTo="https://git.xarth.tv/pages/eventbus/docs/publishers/">
//       Learn more
//     </CoreLink>
//   </CoreText>
// </Layout>
//           </td>
//         </TableRow>
//       )}
//     </Table>
//   </Layout>
// );

// interface AuthorizedFieldSubscriberGrantTableProps {
//   susbcriberGrants: twirp.IAuthorizedFieldSubscriberGrant[];
// }
// const AuthorizedFieldSubscriberGrantTable = ({
//   susbcriberGrants: subscriberGrants,
// }: AuthorizedFieldSubscriberGrantTableProps) => {
//   return (
//     <Table>
//       <TableHeader>
//         <TableHeading label="Event Type" textAlign={TextAlign.Center} />
//         <TableHeading label="Environment" textAlign={TextAlign.Center} />
//         <TableHeading label="Message Name" textAlign={TextAlign.Center} />
//         <TableHeading label="FieldName" textAlign={TextAlign.Center} />
//       </TableHeader>
//       {_.map(subscriberGrants, (grant, i) => {
//         return (
//           <TableRow key={i}>
//             <TableCell textAlign={TextAlign.Center}>
//               {grant.eventType}
//             </TableCell>
//             <TableCell textAlign={TextAlign.Center}>
//               {grant.environment}
//             </TableCell>
//             <TableCell textAlign={TextAlign.Center}>
//               {_.get(grant, "authorizedField.messageName", "")}
//             </TableCell>
//             <TableCell textAlign={TextAlign.Center}>
//               {_.get(grant, "authorizedField.fieldName", "")}
//             </TableCell>
//           </TableRow>
//         );
//       })}
//       {subscriberGrants.length === 0 && (
//         <TableRow>
//           <td colSpan={4}>
//             <Layout
//               padding={1}
//               justifyContent={JustifyContent.Center}
//               display={Display.Flex}
//               fullWidth
//             >
//               <CoreText type={TextType.P} color={Color.Alt2}>
// This role has no grants to decrypt authorized fields.{" "}
// <CoreLink
//   linkTo={
//     "http://git.xarth.tv/pages/eventbus/docs/subscribers/authorized_fields/"
//   }
// >
//   Learn more
//                 </CoreLink>
//               </CoreText>
//             </Layout>
//           </td>
//         </TableRow>
//       )}
//     </Table>
//   );
// };
