import { ReactElement } from 'react';
import { faEye, faEyeSlash, faTrash } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

import { Stack, Tooltip, Divider, Typography, Select, Option, Input, Button } from '@mui/joy';
import { useAppDispatch, useAppSelector } from '../../store/hooks';
import { focusTag, setTabIndex, selectSimilarTags } from '../../store/uiSlice';
import { selectSelectedTabs } from '../../store/selectors';
import { closeTab } from '../../chrome/chromeActions';
import { activateOrOpenTab } from '../../chrome/chromeNavigation';
import { addTag, deletePage, Page, removeTag, fetchPages, updateTodoCompletion, updateTodoPriority, updateTodoDueDate } from '../../db/pages';
import { CustomTagSelector } from '../tagSelector/CustomTagSelector';
import { useLiveQuery } from 'dexie-react-hooks';
import { setSimilarUrlsAsync } from '../../store/windowsSlice';
import { aggregateTags } from '../tagSelector/tag_utils';
import { fetchTagNames } from '../../db/tags';
import { logger } from '../../utils/logger';
import React from 'react';

interface MultiSelectActionsProps {
  selectedUrls: string[];
  onClickTag?: (value: string) => void;
}

const MultiSelectActions = ({
  selectedUrls,
  onClickTag = (_value: string) => {},
}: MultiSelectActionsProps): ReactElement => {
  const dispatch = useAppDispatch();
  const tagOptions: string[] = useLiveQuery(fetchTagNames) as string[];
  const tabs = useAppSelector(selectSelectedTabs);
  const tabUrls = tabs.map((tab) => tab.url).filter((x) => x !== undefined);

  const similarTags = useAppSelector(selectSimilarTags);
  const selectedPages = useLiveQuery(() => fetchPages(selectedUrls), [selectedUrls]) || [];
  const selectedTags = aggregateTags(selectedPages);

  const similarTagsList = Object.values(similarTags)
    .filter((tag) => !(tag.name in selectedTags))
    .sort((a, b) => b.proportion - a.proportion);

  const allUrls = [...new Set([...selectedUrls, ...tabUrls.map((x) => x.normalized)]).values()];

  if (allUrls.length === 0) {
    return <></>;
  }

  const numSelected = allUrls.length;

  // Todo-specific section
  const todoPages = selectedPages.filter((p) => p.completionStatus !== undefined);
  const pendingCount = todoPages.filter((p) => p.completionStatus === 'pending').length;
  const completedCount = todoPages.filter((p) => p.completionStatus === 'completed').length;

  const handleBulkMarkComplete = () => {
    for (const p of todoPages) {
      updateTodoCompletion(p.nurl.normalized, 'completed')
        .catch((err: unknown) => logger.error('[MultiSelectActions] updateTodoCompletion failed', err));
    }
  };

  const handleBulkMarkPending = () => {
    for (const p of todoPages) {
      updateTodoCompletion(p.nurl.normalized, 'pending')
        .catch((err: unknown) => logger.error('[MultiSelectActions] updateTodoCompletion failed', err));
    }
  };

  const handleBulkPriority = (_: React.SyntheticEvent | null, val: number | null) => {
    for (const p of todoPages) {
      updateTodoPriority(p.nurl.normalized, val ?? undefined)
        .catch((err: unknown) => logger.error('[MultiSelectActions] updateTodoPriority failed', err));
    }
  };

  const handleBulkDueDate = (e: React.ChangeEvent<HTMLInputElement>) => {
    const val = e.target.value;
    for (const p of todoPages) {
      updateTodoDueDate(p.nurl.normalized, val ? new Date(val).getTime() : undefined)
        .catch((err: unknown) => logger.error('[MultiSelectActions] updateTodoDueDate failed', err));
    }
  };

  return (
    <Stack direction={'column'} spacing={1}>
      <div>
        {numSelected} {numSelected == 1 ? 'page' : 'pages'} selected
      </div>

      <Stack
        direction={'row'}
        style={{ padding: '5px' }}
        justifyContent="flex-start"
        alignItems="center"
        spacing={1}
        height={'100%'}
      >
        <Tooltip title="Forget tabs forever!" placement="bottom">
          <FontAwesomeIcon
            icon={faTrash}
            onClick={() => {
              for (const tab of tabs) {
                closeTab(tab.id);
              }
              for (const url of selectedUrls) {
                deletePage(url);
              }
              dispatch(setSimilarUrlsAsync());
            }}
            title="Forget Page"
          />
        </Tooltip>

        <Tooltip title="Snooze Tabs" placement="bottom">
          <FontAwesomeIcon
            icon={faEyeSlash}
            onClick={() => {
              for (const tab of tabs) {
                closeTab(tab.id);
              }
            }}
            title="Snooze Tabs"
          />
        </Tooltip>

        <Tooltip title="Open Tabs" placement="bottom">
          <FontAwesomeIcon
            icon={faEye}
            onClick={() => {
              for (const url of allUrls) {
                activateOrOpenTab(url);
              }
            }}
            title="Open Tabs"
          />
        </Tooltip>
      </Stack>

      {todoPages.length > 0 && (
        <>
          <Divider orientation="horizontal" />
          <Typography level="body-xs" sx={{ fontWeight: 'bold', color: '#4a90d9', letterSpacing: '0.05em' }}>
            TODO FIELDS ({pendingCount} pending, {completedCount} done)
          </Typography>
          <Stack direction="row" spacing={1} alignItems="center" flexWrap="wrap">
            <Button size="sm" variant="soft" color="success" onClick={handleBulkMarkComplete} sx={{ fontSize: '0.7rem' }}>
              Mark complete
            </Button>
            <Button size="sm" variant="soft" color="neutral" onClick={handleBulkMarkPending} sx={{ fontSize: '0.7rem' }}>
              Mark pending
            </Button>
          </Stack>
          <Stack direction="row" spacing={1} alignItems="center">
            <Typography level="body-xs" sx={{ flexShrink: 0 }}>Priority:</Typography>
            <Select
              size="sm"
              placeholder="Set priority…"
              onChange={handleBulkPriority}
              sx={{ flex: 1, fontSize: '0.7rem' }}
            >
              <Option value={null}>—</Option>
              <Option value={1}><span style={{ color: '#c0392b', fontWeight: 'bold' }}>P0</span></Option>
              <Option value={2}><span style={{ color: '#e67e22', fontWeight: 'bold' }}>P1</span></Option>
              <Option value={3}><span style={{ color: '#7f8c8d', fontWeight: 'bold' }}>P2</span></Option>
            </Select>
          </Stack>
          <Stack direction="row" spacing={1} alignItems="center">
            <Typography level="body-xs" sx={{ flexShrink: 0 }}>Due date:</Typography>
            <Input
              size="sm"
              type="date"
              onChange={handleBulkDueDate}
              sx={{ flex: 1, fontSize: '0.7rem' }}
            />
          </Stack>
          <Divider orientation="horizontal" />
        </>
      )}

      <Typography level="body-xs" sx={{ fontWeight: 'bold', color: 'text.secondary', letterSpacing: '0.05em' }}>
        APPLIED TAGS
      </Typography>
      <CustomTagSelector
        options={tagOptions}
        attachments={Object.values(selectedTags)}
        onAdd={(value) => {
          if (value != '') {
            addTag(allUrls, value);
            dispatch(setSimilarUrlsAsync());
          }
        }}
        onDelete={(value) => {
          if (value != '') {
            removeTag(allUrls, value);
            dispatch(setSimilarUrlsAsync());
          }
        }}
        onClickTag={onClickTag}
        onDoubleClickTag={(value) => {
          dispatch(focusTag({ tag: value }));
          dispatch(setTabIndex(1));
        }}
        multiSelect={true}
      />

      {similarTagsList.length > 0 && (
        <>
          <Typography level="body-xs" sx={{ fontWeight: 'bold', color: 'text.tertiary', letterSpacing: '0.05em' }}>
            SUGGESTED TAGS
          </Typography>
          <CustomTagSelector
            options={tagOptions}
            attachments={similarTagsList}
            onAdd={(value) => {
              if (value != '') {
                addTag(allUrls, value);
                dispatch(setSimilarUrlsAsync());
              }
            }}
            onDelete={(value) => {
              if (value != '') {
                removeTag(allUrls, value);
                dispatch(setSimilarUrlsAsync());
              }
            }}
            onClickTag={onClickTag}
            onDoubleClickTag={(value) => {
              dispatch(focusTag({ tag: value }));
              dispatch(setTabIndex(1));
            }}
            multiSelect={true}
            hideAddButton={true}
            proposed={true}
          />
        </>
      )}
    </Stack>
  );
};

export default MultiSelectActions;
