import { ReactElement, useState } from 'react';
import { faBullseye } from '@fortawesome/free-solid-svg-icons';
import { faSquare, faSquareCheck } from '@fortawesome/free-regular-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

import { useAppDispatch, useAppSelector } from '../../../store/hooks';
import { PageFilter, PageSortOrder, fetchAllPagesForHumanTag } from '../../../db/pages';
import {
  clearSelectionAndSelectMulti,
  focusTag,
  renameTagInExpanded,
  selectIsExpanded,
  setTagExpanded,
  selectSelectedUrls,
  addMultiToSelection,
  removeMultiFromSelection,
} from '../../../store/uiSlice';
import { useLiveQuery } from 'dexie-react-hooks';
import { formatDistance } from 'date-fns';
import TagPageList from './TagPageList';
import { logger } from '../../../utils/logger';
import CollapsibleSection from './CollapsibleSection';
import Stack from '@mui/joy/Stack';
import { Input, LinearProgress, Tooltip, Typography } from '@mui/joy';
import React from 'react';
import { renameTag, fetchTagLastActive } from '../../../db/tags';

interface CollapsibleTagProps {
  tag: string;
  overrideExpanded?: boolean;
  sortOrder: PageSortOrder;
  filter: PageFilter;
  groupByWindow: boolean;
}

enum TagEditState {
  NONE,
  EDITING,
  RENAMING,
}

const CollapsibleTag = React.memo(
  ({
    tag,
    overrideExpanded = false,
    sortOrder,
    filter,
    groupByWindow,
  }: CollapsibleTagProps): ReactElement => {
    const expanded =
      useAppSelector((rootState) => selectIsExpanded(rootState, tag)) || overrideExpanded;

    const tagAccessTime = useLiveQuery(() => fetchTagLastActive(tag), [tag]);
    
    const pages = useLiveQuery(() => fetchAllPagesForHumanTag(tag), [tag]);
    const tagCount = pages ? pages.length : 0;
    
    const urls = pages ? pages.map((page) => page.nurl) : [];

    const dispatch = useAppDispatch();
    const [tagEditState, setTagEditState] = useState(TagEditState.NONE);

    const selectedUrls = useAppSelector(selectSelectedUrls);
    const allSelected = tagCount > 0 && urls.every((url) => selectedUrls.includes(url.normalized));

    const toggleSelectAll = () => {
      const normalizedUrls = urls.map((u) => u.normalized);
      if (allSelected) {
        dispatch(removeMultiFromSelection(normalizedUrls));
      } else {
        dispatch(addMultiToSelection(normalizedUrls));
      }
    };

    return (
      <CollapsibleSection
        id={'collapsibleTag-' + tag}
        className="collapsibleTag"
        isOpen={expanded}
        onToggle={(val) => dispatch(setTagExpanded({ tag, expanded: val }))}
        prefix={
          <Stack direction="row" spacing={1} alignItems="center">
            <Tooltip title={allSelected ? "Deselect All" : "Select All"} placement="bottom">
              <FontAwesomeIcon
                icon={allSelected ? faSquareCheck : faSquare}
                onClick={(e) => {
                  e.stopPropagation();
                  toggleSelectAll();
                }}
                style={{ cursor: 'pointer' }}
              />
            </Tooltip>
            <Tooltip title="Focus Tag" placement="bottom">
            <FontAwesomeIcon
              icon={faBullseye}
              onClick={() => dispatch(focusTag({ tag }))}
              title="Focus Tag"
              style={{ cursor: 'pointer' }}
            />
            </Tooltip>
          </Stack>
        }
        title={
          tagEditState == TagEditState.EDITING ? (
            <Input
              size="sm"
              name={'tagEdit_' + tag}
              type="text"
              autoFocus
              onInput={(event: React.ChangeEvent<HTMLInputElement>) => {}}
              defaultValue={tag}
              onKeyUp={(event) => {
                if (event.key === 'Escape') {
                  setTagEditState(TagEditState.NONE);
                }
                if (event.key === 'Enter') {
                  logger.info('[Tag] Renaming ' + tag + ' to ' + event.currentTarget.value);
                  renameTag(tag, event.currentTarget.value);
                  setTagEditState(TagEditState.RENAMING);
                  dispatch(renameTagInExpanded({ oldTag: tag, newTag: event.currentTarget.value }));
                }
              }}
            />
          ) : tagEditState == TagEditState.RENAMING ? (
            <LinearProgress
              size="sm"
              sx={{
                verticalAlign: 'middle',
                margin: '0.2rem',
                width: '10rem',
                maxWidth: '10rem',
              }}
            />
          ) : (
            <Typography
              level="title-md"
              component="span"
              onClick={() => {
                if (allSelected) {
                    dispatch(removeMultiFromSelection(urls.map(u => u.normalized)));
                } else {
                    dispatch(
                    clearSelectionAndSelectMulti({
                        urls: urls,
                    })
                    );
                }
              }}
              onDoubleClick={() => setTagEditState(TagEditState.EDITING)}
              sx={{ cursor: 'pointer' }}
            >
              {tag} ({tagCount})
            </Typography>
          )
        }
        suffix={
          <Typography level="body-xs">
            {tagAccessTime && formatDistance(tagAccessTime, new Date(), { addSuffix: true })}
          </Typography>
        }
      >
        <TagPageList
          tag={tag}
          sortOrder={sortOrder}
          filter={filter}
          groupByWindow={groupByWindow}
          expanded={expanded}
        />
      </CollapsibleSection>
    );
  }
);

export default CollapsibleTag;
