import React, { useState, useEffect, useMemo } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { Link } from 'react-router-dom';
import map from 'lodash/map';
import find from 'lodash/find';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { linkIntegrityCheck } from '@plone/volto/actions/content/content';
import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';

import { Confirm, Dimmer, Loader, Table } from 'semantic-ui-react';

const messages = defineMessages({
  deleteConfirmSingleItem: {
    id: 'Delete this item?',
    defaultMessage: 'Delete this item?',
  },
  deleteConfirmMultipleItems: {
    id: 'Delete selected items?',
    defaultMessage: 'Delete selected items?',
  },
  navigate_to_this_item: {
    id: 'Navigate to this item',
    defaultMessage: 'Navigate to this item',
  },
  loading: {
    id: 'link-integrity: loading references',
    defaultMessage: 'Checking references...',
  },
  delete: {
    id: 'Delete',
    defaultMessage: 'Delete',
  },
  delete_and_broken_links: {
    id: 'link-integrity: Delete item and break links',
    defaultMessage: 'Delete item and break links',
  },
  cancel: {
    id: 'Cancel',
    defaultMessage: 'Cancel',
  },
});

const ContentsDeleteModal = (props) => {
  const {
    itemsToDelete = [],
    open,
    onCancel,
    onOk,
    items,
    hasMultiplePages,
  } = props;
  const intl = useIntl();
  const dispatch = useDispatch();
  const linkintegrityInfo = useSelector((state) => state.linkIntegrity?.result);
  const loading = useSelector((state) => state.linkIntegrity?.loading);

  const [brokenReferences, setBrokenReferences] = useState(0);
  const [containedItemsToDelete, setContainedItemsToDelete] = useState([]);
  const [breaches, setBreaches] = useState([]);

  const [linksAndReferencesViewLink, setLinkAndReferencesViewLink] =
    useState(null);

  const titlesToDelete = useMemo(
    () =>
      itemsToDelete.reduce((acc, id) => {
        const item = items.find((item) => item['@id'] === id);
        acc[id] = item ? item.Title : null;
        return acc;
      }, {}),
    [itemsToDelete, items],
  );

  useEffect(() => {
    const getFieldById = (id, field) => {
      const item = find(items, { '@id': id });
      return item ? item[field] : '';
    };

    if (itemsToDelete.length > 0 && open) {
      dispatch(
        linkIntegrityCheck(
          map(itemsToDelete, (item) => getFieldById(item, 'UID')),
        ),
      );
    }
  }, [itemsToDelete, items, open, dispatch]);

  useEffect(() => {
    if (linkintegrityInfo) {
      const containedItems = linkintegrityInfo
        .map((result) => result.items_total ?? 0)
        .reduce((acc, value) => acc + value, 0);
      const breaches = linkintegrityInfo.flatMap((result) =>
        result.breaches.map((source) => ({
          source: source,
          target: result,
        })),
      );
      const source_by_uid = breaches.reduce(
        (acc, value) => acc.set(value.source.uid, value.source),
        new Map(),
      );
      const by_source = breaches.reduce((acc, value) => {
        if (acc.get(value.source.uid) === undefined) {
          acc.set(value.source.uid, new Set());
        }
        acc.get(value.source.uid).add(value.target);
        return acc;
      }, new Map());

      setContainedItemsToDelete(containedItems);
      setBrokenReferences(by_source.size);
      setLinkAndReferencesViewLink(
        linkintegrityInfo.length
          ? linkintegrityInfo[0]['@id'] + '/links-to-item'
          : null,
      );
      setBreaches(
        Array.from(by_source, (entry) => ({
          source: source_by_uid.get(entry[0]),
          targets: Array.from(entry[1]),
        })),
      );
    } else {
      setContainedItemsToDelete([]);
      setBrokenReferences(0);
      setLinkAndReferencesViewLink(null);
      setBreaches([]);
    }
  }, [linkintegrityInfo]);

  return (
    open && (
      <Confirm
        open={open}
        confirmButton={
          brokenReferences === 0
            ? intl.formatMessage(messages.delete)
            : intl.formatMessage(messages.delete_and_broken_links)
        }
        cancelButton={intl.formatMessage(messages.cancel)}
        header={
          itemsToDelete.length === 1
            ? intl.formatMessage(messages.deleteConfirmSingleItem)
            : intl.formatMessage(messages.deleteConfirmMultipleItems)
        }
        content={
          <div className="content">
            <Dimmer active={loading} inverted>
              <Loader indeterminate size="massive">
                {intl.formatMessage(messages.loading)}
              </Loader>
            </Dimmer>

            {itemsToDelete.length > 1 &&
            items.length === itemsToDelete.length ? (
              hasMultiplePages ? (
                <p>
                  <FormattedMessage
                    id="You are about to delete all items in the current pagination of this folder."
                    defaultMessage="You are about to delete all items in the current pagination of this folder."
                  />
                </p>
              ) : (
                <p>
                  <FormattedMessage
                    id="You are about to delete all items in this folder."
                    defaultMessage="You are about to delete all items in this folder."
                  />
                </p>
              )
            ) : (
              <ul>
                {itemsToDelete.map((id) => {
                  return (
                    <li key={id}>
                      <Link to={flattenToAppURL(id)} target="_blank">
                        {titlesToDelete[id] || id}
                      </Link>
                    </li>
                  );
                })}
              </ul>
            )}

            {itemsToDelete.length > 1 ? (
              containedItemsToDelete > 0 ? (
                <>
                  <FormattedMessage
                    id="Some items are also a folder. By deleting them you will delete {containedItemsToDelete} {variation} inside the folders."
                    defaultMessage="Some items are also a folder. By deleting them you will delete {containedItemsToDelete} {variation} inside the folders."
                    values={{
                      containedItemsToDelete: (
                        <span>{containedItemsToDelete}</span>
                      ),
                      variation: (
                        <span>
                          {containedItemsToDelete === 1 ? (
                            <FormattedMessage id="item" defaultMessage="item" />
                          ) : (
                            <FormattedMessage
                              id="items"
                              defaultMessage="items"
                            />
                          )}
                        </span>
                      ),
                    }}
                  />
                  {brokenReferences > 0 && (
                    <>
                      <br />
                      <FormattedMessage
                        id="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
                        defaultMessage="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
                        values={{
                          brokenReferences: <span>{brokenReferences}</span>,
                          variation: (
                            <span>
                              {brokenReferences === 1 ? (
                                <FormattedMessage
                                  id="reference"
                                  defaultMessage="reference"
                                />
                              ) : (
                                <FormattedMessage
                                  id="references"
                                  defaultMessage="references"
                                />
                              )}
                            </span>
                          ),
                        }}
                      />
                    </>
                  )}
                </>
              ) : (
                <>
                  {brokenReferences > 0 && (
                    <>
                      <FormattedMessage
                        id="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
                        defaultMessage="Some items are referenced by other contents. By deleting them {brokenReferences} {variation} will be broken."
                        values={{
                          brokenReferences: <span>{brokenReferences}</span>,
                          variation: (
                            <span>
                              {brokenReferences === 1 ? (
                                <FormattedMessage
                                  id="reference"
                                  defaultMessage="reference"
                                />
                              ) : (
                                <FormattedMessage
                                  id="references"
                                  defaultMessage="references"
                                />
                              )}
                            </span>
                          ),
                        }}
                      />
                    </>
                  )}
                </>
              )
            ) : containedItemsToDelete > 0 ? (
              <>
                <FormattedMessage
                  id="This item is also a folder. By deleting it you will delete {containedItemsToDelete} {variation} inside the folder."
                  defaultMessage="This item is also a folder. By deleting it you will delete {containedItemsToDelete} {variation} inside the folder."
                  values={{
                    containedItemsToDelete: (
                      <span>{containedItemsToDelete}</span>
                    ),
                    variation: (
                      <span>
                        {containedItemsToDelete === 1 ? (
                          <FormattedMessage id="item" defaultMessage="item" />
                        ) : (
                          <FormattedMessage id="items" defaultMessage="items" />
                        )}
                      </span>
                    ),
                  }}
                />
                {brokenReferences > 0 && (
                  <>
                    <br />
                    <FormattedMessage
                      id="Deleting this item breaks {brokenReferences} {variation}."
                      defaultMessage="Deleting this item breaks {brokenReferences} {variation}."
                      values={{
                        brokenReferences: <span>{brokenReferences}</span>,
                        variation: (
                          <span>
                            {brokenReferences === 1 ? (
                              <FormattedMessage
                                id="reference"
                                defaultMessage="reference"
                              />
                            ) : (
                              <FormattedMessage
                                id="references"
                                defaultMessage="references"
                              />
                            )}
                          </span>
                        ),
                      }}
                    />
                    <BrokenLinksList
                      intl={intl}
                      breaches={breaches}
                      linksAndReferencesViewLink={linksAndReferencesViewLink}
                    />
                  </>
                )}
              </>
            ) : brokenReferences > 0 ? (
              <>
                <FormattedMessage
                  id="Deleting this item breaks {brokenReferences} {variation}."
                  defaultMessage="Deleting this item breaks {brokenReferences} {variation}."
                  values={{
                    brokenReferences: <span>{brokenReferences}</span>,
                    variation: (
                      <span>
                        {brokenReferences === 1 ? (
                          <FormattedMessage
                            id="reference"
                            defaultMessage="reference"
                          />
                        ) : (
                          <FormattedMessage
                            id="references"
                            defaultMessage="references"
                          />
                        )}
                      </span>
                    ),
                  }}
                />
                <BrokenLinksList
                  intl={intl}
                  breaches={breaches}
                  linksAndReferencesViewLink={linksAndReferencesViewLink}
                />
              </>
            ) : null}
          </div>
        }
        onCancel={onCancel}
        onConfirm={onOk}
        size="medium"
      />
    )
  );
};

const BrokenLinksList = ({ intl, breaches, linksAndReferencesViewLink }) => {
  return (
    <div className="broken-links-list">
      <FormattedMessage
        id="These items will have broken links"
        defaultMessage="These items will have broken links"
      />
      :
      <Table compact>
        <Table.Body>
          {breaches.map((breach) => (
            <Table.Row key={breach.source['@id']} verticalAlign="top">
              <Table.Cell>
                <Link
                  to={flattenToAppURL(breach.source['@id'])}
                  title={intl.formatMessage(messages.navigate_to_this_item)}
                >
                  {breach.source.title}
                </Link>
              </Table.Cell>
              <Table.Cell style={{ minWidth: '140px' }}>
                <FormattedMessage id="refers to" defaultMessage="refers to" />:
              </Table.Cell>
              <Table.Cell>
                <ul style={{ margin: 0 }}>
                  {breach.targets.map((target) => (
                    <li key={target['@id']}>
                      <Link
                        to={flattenToAppURL(target['@id'])}
                        title={intl.formatMessage(
                          messages.navigate_to_this_item,
                        )}
                      >
                        {target.title}
                      </Link>
                    </li>
                  ))}
                </ul>
              </Table.Cell>
            </Table.Row>
          ))}
        </Table.Body>
      </Table>
      {linksAndReferencesViewLink && (
        <Link to={flattenToAppURL(linksAndReferencesViewLink)}>
          <FormattedMessage
            id="View links and references to this item"
            defaultMessage="View links and references to this item"
          />
        </Link>
      )}
    </div>
  );
};
ContentsDeleteModal.propTypes = {
  itemsToDelete: PropTypes.arrayOf(
    PropTypes.shape({
      UID: PropTypes.string,
    }),
  ).isRequired,
  open: PropTypes.bool.isRequired,
  onOk: PropTypes.func.isRequired,
  onCancel: PropTypes.func.isRequired,
};
export default ContentsDeleteModal;
