import { h, Component } from 'preact';
import PropTypes from 'prop-types';
import he from 'he';
import { getContentOfToken } from '../utilities';
import { locale } from '../../utilities/locale';
import { Navigation } from './Navigation';
import { Spinner } from '@crayons/Spinner/Spinner';

function groupFollowsByType(array) {
  return array.reduce((returning, item) => {
    const type = item.type_identifier;
    returning[type] = (returning[type] || []).concat(item);
    return returning;
  }, {});
}

function groupFollowIdsByType(array) {
  return array.reduce((returning, item) => {
    const type = item.type_identifier;
    returning[type] = (returning[type] || []).concat({ id: item.id });
    return returning;
  }, {});
}

export class FollowUsers extends Component {
  constructor(props) {
    super(props);

    this.handleClick = this.handleClick.bind(this);
    this.handleComplete = this.handleComplete.bind(this);

    this.state = {
      follows: [],
      selectedFollows: [],
      loading: true,
    };
  }

  componentDidMount() {
    fetch('/onboarding/users_and_organizations', {
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      credentials: 'same-origin',
    })
      .then((response) => response.json())
      .then((data) => {
        this.setState({
          selectedFollows: data,
          follows: data,
          loading: false,
        });
      });

    const csrfToken = getContentOfToken('csrf-token');
    fetch('/onboarding', {
      method: 'PATCH',
      headers: {
        'X-CSRF-Token': csrfToken,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        user: { last_onboarding_page: 'v2: follow users page' },
      }),
      credentials: 'same-origin',
    });
  }

  handleComplete() {
    const csrfToken = getContentOfToken('csrf-token');
    const { selectedFollows } = this.state;
    const { next } = this.props;
    const idsGroupedByType = groupFollowIdsByType(selectedFollows);

    fetch('/api/follows', {
      method: 'POST',
      headers: {
        'X-CSRF-Token': csrfToken,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        users: idsGroupedByType['user'],
        organizations: idsGroupedByType['organization'],
      }),
      credentials: 'same-origin',
    });

    next();
  }

  handleSelectAll() {
    const { selectedFollows, follows } = this.state;
    if (selectedFollows.length === follows.length) {
      this.setState({
        selectedFollows: [],
      });
    } else {
      this.setState({
        selectedFollows: follows,
      });
    }
  }

  handleClick(follow) {
    let { selectedFollows } = this.state;

    if (!selectedFollows.includes(follow)) {
      this.setState((prevState) => ({
        selectedFollows: [...prevState.selectedFollows, follow],
      }));
    } else {
      selectedFollows = [...selectedFollows];
      const indexToRemove = selectedFollows.indexOf(follow);
      selectedFollows.splice(indexToRemove, 1);
      this.setState({
        selectedFollows,
      });
    }
  }

  renderFollowCount() {
    const { follows, selectedFollows } = this.state;

    let followingStatus;
    if (selectedFollows.length === 0) {
      followingStatus = locale('core.not_following');
    } else {
      const groups = groupFollowsByType(selectedFollows);
      let together = [];
      for (const type in groups) {
        const counted = locale(`core.counted_${type}`, {
          count: groups[type].length,
        });
        together = together.concat(counted);
      }

      const anded_together = together.join(` ${locale('core.and')} `);

      if (selectedFollows.length === follows.length) {
        followingStatus = `${locale('core.following_everyone', {
          details: anded_together,
        })}`;
      } else {
        followingStatus = `${locale(
          'core.you_are_following',
        )} ${anded_together}`;
      }
    }

    const klassName =
      selectedFollows.length > 0
        ? 'fw-bold color-base-60 inline-block fs-base'
        : 'color-base-60 inline-block fs-base';

    return <p className={klassName}>{followingStatus} -</p>;
  }

  renderFollowToggle() {
    const { follows, selectedFollows } = this.state;
    let followText = '';

    if (selectedFollows.length !== follows.length) {
      if (follows.length === 1) {
        followText = `Select ${follows.length}`;
      } else {
        followText = `Select all ${follows.length}`;
      }
    } else {
      followText = 'Deselect all';
    }

    return (
      <button
        type="button"
        class="crayons-btn crayons-btn--ghost-brand -ml-2"
        onClick={() => this.handleSelectAll()}
      >
        {followText}
      </button>
    );
  }

  render() {
    const { follows, selectedFollows, loading } = this.state;
    const { prev, slidesCount, currentSlideIndex } = this.props;
    const canSkip = selectedFollows.length === 0;

    return (
      <div
        data-testid="onboarding-follow-users"
        className="onboarding-main crayons-modal crayons-modal--large"
      >
        <div
          className="crayons-modal__box overflow-auto"
          role="dialog"
          aria-labelledby="title"
          aria-describedby="subtitle"
        >
          <Navigation
            prev={prev}
            next={this.handleComplete}
            canSkip={canSkip}
            slidesCount={slidesCount}
            currentSlideIndex={currentSlideIndex}
          />
          <div className="onboarding-content toggle-bottom">
            <header className="onboarding-content-header">
              <h1 id="title" className="title">
                Suggested follows
              </h1>
              <h2 id="subtitle" className="subtitle">
                Kickstart your community
              </h2>
              <div className="onboarding-selection-status">
                {this.renderFollowCount()}
                {this.renderFollowToggle()}
              </div>
              <div
                className={`loading-spinner align-center ${
                  loading ? '' : 'hidden'
                }`}
              >
                <Spinner />
              </div>
            </header>

            <fieldset data-testid="onboarding-users">
              {follows.map((follow) => {
                const selected = selectedFollows.includes(follow);

                return (
                  <div
                    key={`${follow.id}-${follow.type_identifier}`}
                    data-testid="onboarding-user-button"
                    className={`user content-row ${
                      selected ? 'selected' : 'unselected'
                    }`}
                  >
                    <figure className="user-avatar-container">
                      <img
                        className="user-avatar"
                        src={follow.profile_image_url}
                        alt=""
                        loading="lazy"
                      />
                    </figure>
                    <div className="user-info">
                      <h4 className="user-name">{follow.name}</h4>
                      <p className="user-summary">
                        {he.unescape(follow.summary || '')}
                      </p>
                    </div>
                    <label
                      className={`relative user-following-status crayons-btn ${
                        selected ? 'crayons-btn--outlined' : 'color-primary'
                      }`}
                    >
                      <input
                        aria-label={`Follow ${follow.name}`}
                        type="checkbox"
                        checked={selected}
                        className="absolute opacity-0 absolute top-0 bottom-0 right-0 left-0"
                        onClick={() => this.handleClick(follow)}
                        data-testid="onboarding-user-following-status"
                      />
                      {selected ? 'Following' : 'Follow'}
                    </label>
                  </div>
                );
              })}
            </fieldset>
          </div>
        </div>
      </div>
    );
  }
}

FollowUsers.propTypes = {
  prev: PropTypes.func.isRequired,
  next: PropTypes.string.isRequired,
  slidesCount: PropTypes.number.isRequired,
  currentSlideIndex: PropTypes.func.isRequired,
};
