import { useCallback, useEffect, useRef, useState } from 'react';
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Subplebbit, useAccount, useAccountSubplebbits } from '@plebbit/plebbit-react-hooks';
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import useHomeFiltersStore from '../../../stores/use-home-filters-store';
import { useMultisubMetadata } from '../../../hooks/use-default-subplebbits';
import styles from '../home.module.css';
import { nsfwTags } from '../home';

const BoxModal = ({ isBoardsBoxModal }: { isBoardsBoxModal: boolean }) => {
  const { t } = useTranslation();
  const [showFilterModal, setShowFilterModal] = useState(false);
  const modalRef = useRef<HTMLDivElement>(null);

  const {
    showNsfwBoardsOnly,
    setShowNsfwBoardsOnly,
    showWorksafeBoardsOnly,
    setShowWorksafeBoardsOnly,
    useCatalog,
    setUseCatalog,
    showWorksafeContentOnly,
    setShowWorksafeContentOnly,
    showNsfwContentOnly,
    setShowNsfwContentOnly,
  } = useHomeFiltersStore();

  const handleClickOutside = useCallback(
    (event: MouseEvent) => {
      if (modalRef.current && !modalRef.current.contains(event.target as Node)) {
        setShowFilterModal(false);
      }
    },
    [modalRef, setShowFilterModal],
  );

  useEffect(() => {
    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, [handleClickOutside]);

  return (
    <>
      <span ref={modalRef} onClick={() => setShowFilterModal(true)}>
        {isBoardsBoxModal ? t('filter') : t('options')} ▼
      </span>
      {showFilterModal && (
        <div ref={modalRef} className={styles.filterModal}>
          {isBoardsBoxModal ? (
            <>
              <div
                className={`${styles.option} ${!showNsfwBoardsOnly && !showWorksafeBoardsOnly && styles.selected}`}
                onClick={() => {
                  setShowNsfwBoardsOnly(false);
                  setShowWorksafeBoardsOnly(false);
                  setShowFilterModal(false);
                }}
              >
                Show All Boards
              </div>
              <div
                className={`${styles.option} ${showNsfwBoardsOnly && styles.selected}`}
                onClick={() => {
                  if (showWorksafeBoardsOnly) {
                    setShowWorksafeBoardsOnly(false);
                  }
                  setShowNsfwBoardsOnly(!showNsfwBoardsOnly);
                  setShowFilterModal(false);
                }}
              >
                Show NSFW Boards Only
              </div>
              <div
                className={`${styles.option} ${showWorksafeBoardsOnly && styles.selected}`}
                onClick={() => {
                  if (showNsfwBoardsOnly) {
                    setShowNsfwBoardsOnly(false);
                  }
                  setShowWorksafeBoardsOnly(!showWorksafeBoardsOnly);
                  setShowFilterModal(false);
                }}
              >
                Show Worksafe Boards Only
              </div>
              <div className={styles.separator} />
              <div
                className={`${styles.option} ${useCatalog && styles.selected}`}
                onClick={() => {
                  setUseCatalog(!useCatalog);
                  setShowFilterModal(false);
                }}
              >
                Use Catalog
              </div>
            </>
          ) : (
            <>
              <div
                className={`${styles.option} ${showWorksafeContentOnly && styles.selected}`}
                onClick={() => {
                  if (showNsfwContentOnly) {
                    setShowNsfwContentOnly(false);
                  }
                  setShowWorksafeContentOnly(!showWorksafeContentOnly);
                  setShowFilterModal(false);
                }}
              >
                Show Worksafe Content Only
              </div>
              <div
                className={`${styles.option} ${showNsfwContentOnly && styles.selected}`}
                onClick={() => {
                  if (showWorksafeContentOnly) {
                    setShowWorksafeContentOnly(false);
                  }
                  setShowNsfwContentOnly(!showNsfwContentOnly);
                  setShowFilterModal(false);
                }}
              >
                Show NSFW Content Only
              </div>
              <div
                className={`${styles.option} ${!showWorksafeContentOnly && !showNsfwContentOnly && styles.selected}`}
                onClick={() => {
                  setShowWorksafeContentOnly(false);
                  setShowNsfwContentOnly(false);
                  setShowFilterModal(false);
                }}
              >
                Show All Content
              </div>
            </>
          )}
        </div>
      )}
    </>
  );
};

const Board = ({ isOffline, subplebbit }: { isOffline: boolean; subplebbit: Subplebbit }) => {
  const { t } = useTranslation();
  const { address, title, tags } = subplebbit || {};
  const nsfwTag = tags.find((tag: string) => nsfwTags.includes(tag));
  const { useCatalog } = useHomeFiltersStore();

  const boardLink = useCatalog ? `/p/${address}/catalog` : `/p/${address}`;

  return (
    <div className={styles.subplebbit} key={address}>
      {isOffline && <span className={styles.offlineIcon} />}
      <Link to={boardLink}>{title || address}</Link>
      {nsfwTag && <span className={styles.nsfw}> ({t(nsfwTag)})</span>}
    </div>
  );
};

const BoardsBox = ({ multisub, subplebbits }: { multisub: Subplebbit[]; subplebbits: any }) => {
  const { t } = useTranslation();
  const account = useAccount();
  const subscriptions = account?.subscriptions || [];
  const { accountSubplebbits } = useAccountSubplebbits();
  const accountSubplebbitAddresses = Object.keys(accountSubplebbits);
  const { showNsfwBoardsOnly, showWorksafeBoardsOnly } = useHomeFiltersStore();

  const filterSubs = (subs: Subplebbit[], includeTags: string[], excludeTags: string[] = []) =>
    subs.filter((sub) => includeTags.every((tag) => sub.tags?.includes(tag)) && excludeTags.every((tag) => !sub.tags?.includes(tag)));

  let plebbitSubs = filterSubs(multisub, ['plebbit']);
  let interestsSubs = filterSubs(multisub, ['topic'], ['plebbit', 'country', 'international']);
  let randomSubs = filterSubs(multisub, ['random'], ['plebbit']);
  let internationalSubs = filterSubs(multisub, ['international']);
  let projectsSubs = filterSubs(multisub, ['project'], ['plebbit', 'topic']);

  const filterByNsfw = (subs: Subplebbit[], includeNsfw: boolean) => subs.filter((sub) => sub.tags.some((tag: string) => nsfwTags.includes(tag)) === includeNsfw);

  const filterCategoriesByNsfw = (subsArray: Subplebbit[][], includeNsfw: boolean) => subsArray.map((subs) => filterByNsfw(subs, includeNsfw));

  const includeNsfw = showNsfwBoardsOnly ? true : showWorksafeBoardsOnly ? false : null;

  if (includeNsfw !== null) {
    [plebbitSubs, interestsSubs, randomSubs, internationalSubs, projectsSubs] = filterCategoriesByNsfw(
      [plebbitSubs, interestsSubs, randomSubs, internationalSubs, projectsSubs],
      includeNsfw,
    );
  }

  const isSubOffline = (address: string) => {
    const subplebbit = subplebbits && subplebbits.find((sub: Subplebbit) => sub?.address === address);
    const isOffline = subplebbit?.updatedAt && subplebbit.updatedAt < Date.now() / 1000 - 60 * 60;
    return isOffline;
  };

  const multisubMetadata = useMultisubMetadata();

  return (
    <div className={`${styles.box} ${styles.boardsBox}`}>
      <div className={styles.boxBar}>
        <h2 className='capitalize'>{t('boards')}</h2>
        <BoxModal isBoardsBoxModal={true} />
      </div>
      <div className={styles.boardsBoxContent}>
        <div className={styles.column}>
          <h3>Multiboards</h3>
          <div className={styles.list}>
            <div className={styles.subplebbit}>
              <Link to='/p/all'>{multisubMetadata?.title || 'All'}</Link>
            </div>
            <div className={styles.subplebbit}>
              <Link to='/p/subscriptions'>Subscriptions</Link>
            </div>
          </div>
          {plebbitSubs.length > 0 && (
            <>
              <h3>Plebbit</h3>
              <div className={styles.list}>
                {plebbitSubs.map((sub) => (
                  <Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
                ))}
              </div>
            </>
          )}
          {projectsSubs.length > 0 && (
            <>
              <h3>{t('projects')}</h3>
              <div className={styles.list}>
                {projectsSubs.map((sub) => (
                  <Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
                ))}
              </div>
            </>
          )}
        </div>
        <div className={styles.column}>
          {interestsSubs.length > 0 && (
            <>
              <h3>{t('interests')}</h3>
              <div className={styles.list}>
                {interestsSubs.map((sub) => (
                  <Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
                ))}
              </div>
            </>
          )}
        </div>
        <div className={styles.column}>
          {randomSubs.length > 0 && (
            <>
              <h3>{t('random')}</h3>
              <div className={styles.list}>
                {randomSubs.map((sub) => (
                  <Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
                ))}
              </div>
            </>
          )}
          {internationalSubs.length > 0 && (
            <>
              <h3>{t('international')}</h3>
              <div className={styles.list}>
                {internationalSubs.map((sub) => (
                  <Board key={sub.address} subplebbit={sub} isOffline={sub.address && isSubOffline(sub.address)} />
                ))}
              </div>
            </>
          )}
        </div>
        <div className={styles.column}>
          <div className={styles.list}>
            <h3>{t('subscriptions')}</h3>
            {subscriptions.length > 0
              ? subscriptions.map((address: string, index: number) => (
                  <div className={styles.subplebbit} key={index}>
                    <Link to={`/p/${address}`}>p/{address && Plebbit.getShortAddress(address)}</Link>
                  </div>
                ))
              : t('not_subscribed')}
          </div>
          <div className={styles.list}>
            <h3>{t('moderating')}</h3>
            {accountSubplebbitAddresses.length > 0
              ? accountSubplebbitAddresses.map((address: string, index: number) => (
                  <div className={styles.subplebbit} key={index}>
                    <Link to={`/p/${address}`}>p/{address && Plebbit.getShortAddress(address)}</Link>
                  </div>
                ))
              : t('not_moderating')}
          </div>
        </div>
      </div>
    </div>
  );
};

export default BoardsBox;
