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

import { defineMessages, useIntl, FormattedMessage } from 'react-intl';

import { Helmet } from 'react-helmet';
import { useParams, useHistory, Link } from 'react-router-dom';

import { isFulfilled } from '@reduxjs/toolkit';

import Toggle from 'react-toggle';

import AntennaIcon from '@/material-icons/400-24px/wifi.svg?react';
import { fetchAntenna } from 'mastodon/actions/antennas';
import { createAntenna, updateAntenna } from 'mastodon/actions/antennas_typed';
import { fetchLists } from 'mastodon/actions/lists';
import Column from 'mastodon/components/column';
import { ColumnHeader } from 'mastodon/components/column_header';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import { getOrderedLists } from 'mastodon/selectors/lists';
import { useAppDispatch, useAppSelector } from 'mastodon/store';

const messages = defineMessages({
  edit: { id: 'column.edit_antenna', defaultMessage: 'Edit antenna' },
  create: { id: 'column.create_antenna', defaultMessage: 'Create antenna' },
});

const FiltersLink: React.FC<{
  id: string;
}> = ({ id }) => {
  return (
    <Link to={`/antennas/${id}/filtering`} className='app-form__link'>
      <div className='app-form__link__text'>
        <strong>
          <FormattedMessage
            id='antennas.filter_items'
            defaultMessage='Antenna filter settings'
          />
        </strong>
      </div>
    </Link>
  );
};

const NewAntenna: React.FC<{
  multiColumn?: boolean;
}> = ({ multiColumn }) => {
  const dispatch = useAppDispatch();
  const { id } = useParams<{ id?: string }>();
  const intl = useIntl();
  const history = useHistory();

  const antenna = useAppSelector((state) =>
    id ? state.antennas.get(id) : undefined,
  );
  const lists = useAppSelector((state) => getOrderedLists(state));
  const [title, setTitle] = useState('');
  const [stl, setStl] = useState(false);
  const [ltl, setLtl] = useState(false);
  const [insertFeeds, setInsertFeeds] = useState(false);
  const [listId, setListId] = useState('');
  const [withMediaOnly, setWithMediaOnly] = useState(false);
  const [ignoreReblog, setIgnoreReblog] = useState(false);
  const [mode, setMode] = useState('filtering');
  const [destination, setDestination] = useState('home');
  const [submitting, setSubmitting] = useState(false);

  useEffect(() => {
    if (id) {
      dispatch(fetchAntenna(id));
      dispatch(fetchLists());
    }
  }, [dispatch, id]);

  useEffect(() => {
    if (id && antenna) {
      setTitle(antenna.title);
      setStl(antenna.stl);
      setLtl(antenna.ltl);
      setInsertFeeds(antenna.insert_feeds);
      setListId(antenna.list?.id ?? '0');
      setWithMediaOnly(antenna.with_media_only);
      setIgnoreReblog(antenna.ignore_reblog);

      if (antenna.stl) {
        setMode('stl');
      } else if (antenna.ltl) {
        setMode('ltl');
      } else {
        setMode('filtering');
      }

      if (antenna.insert_feeds) {
        if (antenna.list) {
          setDestination('list');
        } else {
          setDestination('home');
        }
      } else {
        setDestination('timeline');
      }
    }
  }, [
    setTitle,
    setStl,
    setLtl,
    setInsertFeeds,
    setListId,
    setWithMediaOnly,
    setIgnoreReblog,
    setMode,
    setDestination,
    id,
    antenna,
    lists,
  ]);

  const handleTitleChange = useCallback(
    ({ target: { value } }: React.ChangeEvent<HTMLInputElement>) => {
      setTitle(value);
    },
    [setTitle],
  );

  const handleListIdChange = useCallback(
    ({ target: { value } }: React.ChangeEvent<HTMLSelectElement>) => {
      setListId(value);
    },
    [setListId],
  );

  const handleModeChange = useCallback(
    ({ target: { value } }: React.ChangeEvent<HTMLSelectElement>) => {
      if (value === 'stl') {
        setStl(true);
        setLtl(false);
      } else if (value === 'ltl') {
        setStl(false);
        setLtl(true);
      } else if (value === 'filtering') {
        setStl(false);
        setLtl(false);
      }

      setMode(value);
    },
    [setLtl, setStl, setMode, listId, setListId, lists],
  );

  const handleDestinationChange = useCallback(
    ({ target: { value } }: React.ChangeEvent<HTMLSelectElement>) => {
      if (value === 'list') {
        setInsertFeeds(true);
        if (listId === '0' && lists.length > 0) {
          setListId(lists[0]?.id ?? '0');
        }
      } else if (value === 'home') {
        setInsertFeeds(true);
        // listId = 0
      } else if (value === 'timeline') {
        setInsertFeeds(false);
      }

      setDestination(value);
    },
    [setDestination, setListId, listId, lists],
  );

  const handleWithMediaOnlyChange = useCallback(
    ({ target: { checked } }: React.ChangeEvent<HTMLInputElement>) => {
      setWithMediaOnly(checked);
    },
    [setWithMediaOnly],
  );

  const handleIgnoreReblogChange = useCallback(
    ({ target: { checked } }: React.ChangeEvent<HTMLInputElement>) => {
      setIgnoreReblog(checked);
    },
    [setIgnoreReblog],
  );

  const handleSubmit = useCallback(() => {
    setSubmitting(true);

    if (id) {
      void dispatch(
        updateAntenna({
          id,
          title,
          stl,
          ltl,
          insert_feeds: insertFeeds,
          list_id: destination === 'list' ? listId : '0',
          with_media_only: withMediaOnly,
          ignore_reblog: ignoreReblog,
        }),
      ).then(() => {
        setSubmitting(false);
        return '';
      });
    } else {
      void dispatch(
        createAntenna({
          title,
          stl,
          ltl,
          insert_feeds: insertFeeds,
          list_id: destination === 'list' ? listId : '0',
          with_media_only: withMediaOnly,
          ignore_reblog: ignoreReblog,
        }),
      ).then((result) => {
        setSubmitting(false);

        if (isFulfilled(result)) {
          history.replace(`/antennas/${result.payload.id}/edit`);
          history.push(`/antennas/${result.payload.id}/members`);
        }

        return '';
      });
    }
  }, [
    history,
    dispatch,
    setSubmitting,
    id,
    title,
    stl,
    ltl,
    insertFeeds,
    listId,
    withMediaOnly,
    ignoreReblog,
    destination,
  ]);

  return (
    <Column
      bindToDocument={!multiColumn}
      label={intl.formatMessage(id ? messages.edit : messages.create)}
    >
      <ColumnHeader
        title={intl.formatMessage(id ? messages.edit : messages.create)}
        icon='antenna-ul'
        iconComponent={AntennaIcon}
        multiColumn={multiColumn}
        showBackButton
      />

      <div className='scrollable'>
        <form className='simple_form app-form' onSubmit={handleSubmit}>
          <div className='fields-group'>
            <div className='input with_label'>
              <div className='label_input'>
                <label htmlFor='antenna_title'>
                  <FormattedMessage
                    id='antennas.antenna_name'
                    defaultMessage='Antenna name'
                  />
                </label>

                <div className='label_input__wrapper'>
                  <input
                    id='antenna_title'
                    type='text'
                    value={title}
                    onChange={handleTitleChange}
                    maxLength={30}
                    required
                    placeholder=' '
                  />
                </div>
              </div>
            </div>
          </div>

          <div className='fields-group'>
            <div className='input with_label'>
              <div className='label_input'>
                <label htmlFor='antenna_list'>
                  <FormattedMessage id='antennas.mode' defaultMessage='Mode' />
                </label>

                <div className='label_input__wrapper'>
                  <select
                    id='antenna_insert_list'
                    value={mode}
                    onChange={handleModeChange}
                  >
                    <FormattedMessage
                      id='antennas.mode.stl'
                      defaultMessage='Social timeline mode'
                    >
                      {(msg) => <option value='stl'>{msg}</option>}
                    </FormattedMessage>
                    <FormattedMessage
                      id='antennas.mode.ltl'
                      defaultMessage='Local timeline mode'
                    >
                      {(msg) => <option value='ltl'>{msg}</option>}
                    </FormattedMessage>
                    <FormattedMessage
                      id='antennas.mode.filtering'
                      defaultMessage='Filtering'
                    >
                      {(msg) => <option value='filtering'>{msg}</option>}
                    </FormattedMessage>
                  </select>
                </div>
              </div>
            </div>
          </div>

          <div className='fields-group'>
            <div className='input with_label'>
              <div className='label_input'>
                <label htmlFor='antenna_list'>
                  <FormattedMessage
                    id='antennas.destination'
                    defaultMessage='Destination'
                  />
                </label>

                <div className='label_input__wrapper'>
                  <select
                    id='antenna_insert_destination'
                    value={destination}
                    onChange={handleDestinationChange}
                  >
                    <FormattedMessage
                      id='antennas.destination.home'
                      defaultMessage='Insert to home'
                    >
                      {(msg) => <option value='home'>{msg}</option>}
                    </FormattedMessage>
                    <FormattedMessage
                      id='antennas.destination.list'
                      defaultMessage='Insert to list'
                    >
                      {(msg) => <option value='list'>{msg}</option>}
                    </FormattedMessage>
                    <FormattedMessage
                      id='antennas.destination.timeline'
                      defaultMessage='Antenna timeline only'
                    >
                      {(msg) => <option value='timeline'>{msg}</option>}
                    </FormattedMessage>
                  </select>
                </div>
              </div>
            </div>
          </div>

          {destination === 'list' && (
            <div className='fields-group'>
              <div className='input with_label'>
                <div className='label_input'>
                  <label htmlFor='antenna_list'>
                    <FormattedMessage
                      id='antennas.insert_list'
                      defaultMessage='List'
                    />
                  </label>

                  <div className='label_input__wrapper'>
                    <select
                      id='antenna_insert_list'
                      value={listId}
                      onChange={handleListIdChange}
                    >
                      {lists.map((list) => (
                        <option key={list.id} value={list.id}>
                          {list.title}
                        </option>
                      ))}
                    </select>
                  </div>
                </div>
              </div>
            </div>
          )}

          {id && mode === 'filtering' && (
            <>
              <div className='fields-group'>
                <FiltersLink id={id} />
              </div>

              <div className='fields-group'>
                {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
                <label className='app-form__toggle'>
                  <div className='app-form__toggle__label'>
                    <strong>
                      <FormattedMessage
                        id='antennas.media_only'
                        defaultMessage='Media only'
                      />
                    </strong>
                    <span className='hint'>
                      <FormattedMessage
                        id='antennas.media_only_hint'
                        defaultMessage='Only posts with media will be added antenna.'
                      />
                    </span>
                  </div>

                  <div className='app-form__toggle__toggle'>
                    <div>
                      <Toggle
                        checked={withMediaOnly}
                        onChange={handleWithMediaOnlyChange}
                      />
                    </div>
                  </div>
                </label>
              </div>

              <div className='fields-group'>
                {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
                <label className='app-form__toggle'>
                  <div className='app-form__toggle__label'>
                    <strong>
                      <FormattedMessage
                        id='antennas.ignore_reblog'
                        defaultMessage='Exclude boosts'
                      />
                    </strong>
                    <span className='hint'>
                      <FormattedMessage
                        id='antennas.ignore_reblog_hint'
                        defaultMessage='Boosts will be excluded from antenna detection.'
                      />
                    </span>
                  </div>

                  <div className='app-form__toggle__toggle'>
                    <div>
                      <Toggle
                        checked={ignoreReblog}
                        onChange={handleIgnoreReblogChange}
                      />
                    </div>
                  </div>
                </label>
              </div>
            </>
          )}

          <div className='actions'>
            <button className='button' type='submit'>
              {submitting ? (
                <LoadingIndicator />
              ) : id ? (
                <FormattedMessage id='antennas.save' defaultMessage='Save' />
              ) : (
                <FormattedMessage
                  id='antennas.create'
                  defaultMessage='Create'
                />
              )}
            </button>
          </div>
        </form>
      </div>

      <Helmet>
        <title>
          {intl.formatMessage(id ? messages.edit : messages.create)}
        </title>
        <meta name='robots' content='noindex' />
      </Helmet>
    </Column>
  );
};

// eslint-disable-next-line import/no-default-export
export default NewAntenna;
