import {Component, Fragment} from 'react';
import type {RouteComponentProps} from 'react-router';
import styled from '@emotion/styled';

import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
import type {ModalRenderProps} from 'sentry/actionCreators/modal';
import {openModal} from 'sentry/actionCreators/modal';
import {Button} from 'sentry/components/button';
import RadioGroup from 'sentry/components/forms/controls/radioGroup';
import Form from 'sentry/components/forms/form';
import JsonForm from 'sentry/components/forms/jsonForm';
import FormModel from 'sentry/components/forms/model';
import type {JsonFormObject} from 'sentry/components/forms/types';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {User} from 'sentry/types/user';
import {browserHistory} from 'sentry/utils/browserHistory';
import DeprecatedAsyncView from 'sentry/views/deprecatedAsyncView';

const userEditForm: JsonFormObject = {
  title: 'User details',
  fields: [
    {
      name: 'name',
      type: 'string',
      required: true,
      label: t('Name'),
    },
    {
      name: 'username',
      type: 'string',
      required: true,
      label: t('Username'),
      help: t('The username is the unique id of the user in the system'),
    },
    {
      name: 'email',
      type: 'string',
      required: true,
      label: t('Email'),
      help: t('The users primary email address'),
    },
    {
      name: 'isActive',
      type: 'boolean',
      required: true,
      label: t('Active'),
      help: t(
        'Designates whether this user should be treated as active. Unselect this instead of deleting accounts.'
      ),
    },
    {
      name: 'isStaff',
      type: 'boolean',
      required: true,
      label: t('Admin'),
      help: t('Designates whether this user can perform administrative functions.'),
    },
    {
      name: 'isSuperuser',
      type: 'boolean',
      required: true,
      label: t('Superuser'),
      help: t(
        'Designates whether this user has all permissions without explicitly assigning them.'
      ),
    },
  ],
};

const REMOVE_BUTTON_LABEL = {
  disable: t('Disable User'),
  delete: t('Permanently Delete User'),
};

type DeleteType = 'disable' | 'delete';

type RemoveModalProps = ModalRenderProps & {
  onRemove: (type: DeleteType) => void;
  user: User;
};

type RemoveModalState = {
  deleteType: DeleteType;
};

class RemoveUserModal extends Component<RemoveModalProps, RemoveModalState> {
  state: RemoveModalState = {
    deleteType: 'disable',
  };

  onRemove = () => {
    this.props.onRemove(this.state.deleteType);
    this.props.closeModal();
  };

  render() {
    const {user} = this.props;
    const {deleteType} = this.state;

    return (
      <Fragment>
        <RadioGroup
          value={deleteType}
          label={t('Remove user %s', user.email)}
          onChange={type => this.setState({deleteType: type})}
          choices={[
            ['disable', t('Disable the account.')],
            ['delete', t('Permanently remove the user and their data.')],
          ]}
        />
        <ModalFooter>
          <Button priority="danger" onClick={this.onRemove}>
            {REMOVE_BUTTON_LABEL[deleteType]}
          </Button>
          <Button onClick={this.props.closeModal}>{t('Cancel')}</Button>
        </ModalFooter>
      </Fragment>
    );
  }
}

type Props = DeprecatedAsyncView['props'] & RouteComponentProps<{id: string}, {}>;

type State = DeprecatedAsyncView['state'] & {
  user: User | null;
};

class AdminUserEdit extends DeprecatedAsyncView<Props, State> {
  get userEndpoint() {
    const {params} = this.props;
    return `/users/${params.id}/`;
  }

  getEndpoints(): ReturnType<DeprecatedAsyncView['getEndpoints']> {
    return [['user', this.userEndpoint]];
  }

  async deleteUser() {
    await this.api.requestPromise(this.userEndpoint, {
      method: 'DELETE',
      data: {hardDelete: true, organizations: []},
    });

    addSuccessMessage(t("%s's account has been deleted.", this.state.user?.email));
    browserHistory.replace('/manage/users/');
  }

  async deactivateUser() {
    const response = await this.api.requestPromise(this.userEndpoint, {
      method: 'PUT',
      data: {isActive: false},
    });

    this.setState({user: response});
    this.formModel.setInitialData(response);
    addSuccessMessage(t("%s's account has been deactivated.", response.email));
  }

  removeUser = (actionTypes: DeleteType) =>
    actionTypes === 'delete' ? this.deleteUser() : this.deactivateUser();

  formModel = new FormModel();

  renderBody() {
    const {user} = this.state;

    if (user === null) {
      return null;
    }

    const openDeleteModal = () =>
      openModal(opts => (
        <RemoveUserModal user={user} onRemove={this.removeUser} {...opts} />
      ));

    return (
      <Fragment>
        <h3>{t('Users')}</h3>
        <p>{t('Editing user: %s', user.email)}</p>
        <Form
          model={this.formModel}
          initialData={user}
          apiMethod="PUT"
          apiEndpoint={this.userEndpoint}
          requireChanges
          onSubmitError={err => {
            addErrorMessage(err?.responseJSON?.detail);
          }}
          onSubmitSuccess={data => {
            this.setState({user: data});
            addSuccessMessage(t('User account updated.'));
          }}
          extraButton={
            <Button
              onClick={openDeleteModal}
              style={{marginLeft: space(1)}}
              priority="danger"
            >
              {t('Remove User')}
            </Button>
          }
        >
          <JsonForm forms={[userEditForm]} />
        </Form>
      </Fragment>
    );
  }
}

const ModalFooter = styled('div')`
  display: grid;
  grid-auto-flow: column;
  gap: ${space(1)};
  justify-content: end;
  padding: 20px 30px;
  margin: 20px -30px -30px;
  border-top: 1px solid ${p => p.theme.border};
`;

export default AdminUserEdit;