import { ReactElement, useMemo } from 'react';

import { useAppSelector } from '../../store/hooks';
import { RootState } from '../../store/rootState';

import { makeSelectTabsForWindow, selectWindow } from '../../store/windowsSlice';
import 'date-fns';
import WindowTabListHeader from './WindowTabListHeader';
import { Page, PageFilter, fetchPagesByNormalizedUrls } from '../../db/pages';
import PageRow from '../flexView/pagelists/pagerow/PageRow';
import { useLiveQuery } from 'dexie-react-hooks';
import { NormalizedUrl } from '../../chrome/normalizeUrl';
import React from 'react';
import { filterPage } from '../sort';
import { sortBy } from 'lodash';
import { pageSortOrderMap } from '../sort';
import { PageSortOrder } from '../../db/pages';
import { selectSimilarUrls, selectSelectedUrls } from '../../store/uiSlice';

interface WindowRowProps {
  windowId: number;
  filter: PageFilter;
  sortOrder: PageSortOrder;
}

const WindowTabList = React.memo(({ windowId, filter, sortOrder }: WindowRowProps): ReactElement => {
  const selectTabsForWindow = useMemo(makeSelectTabsForWindow, []);

  const window = useAppSelector((state: RootState) => selectWindow(state, windowId));
  const tabs = useAppSelector((state: RootState) => selectTabsForWindow(state, windowId));
  const similarUrls = useAppSelector(selectSimilarUrls);
  const selectedUrls = useAppSelector(selectSelectedUrls);
  const urls = useMemo(() => tabs.map((tab) => tab.url).filter(Boolean) as NormalizedUrl[], [tabs]);
  // const pages = useLiveQuery(
  //   monitorAsync(() => selectPagesByNormalizedUrls(urls), 'selectPagesByNormalizedUrls'),
  //   [urls]
  // );
  const pages = useLiveQuery(() => fetchPagesByNormalizedUrls(urls), [urls]);
  if (!tabs || tabs.length === 0 || !pages || pages.length === 0) {
    return <></>;
  }

  const normalizedUrlToPage: { [key: string]: Page } = pages
    ? Object.fromEntries(pages.map((page) => [page.nurl.normalized, page]))
    : {};

  if (window === undefined || tabs === undefined || urls === undefined || pages === undefined) {
    return <></>;
  }

  let tabsToRender = tabs;
  
  if (sortOrder === PageSortOrder.similarity) {
       tabsToRender = sortBy(tabs, [
          (tab) => !selectedUrls.includes(tab.url?.normalized || ''),
          (tab) => {
              const nurl = tab.url?.normalized;
              return -(similarUrls[nurl || ''] || 0);
          }
      ]);
  } else if (sortOrder !== PageSortOrder.recent) {
      // Sort tabs based on page properties
      // Note: If duplicates exist, this sort is stable? lodash sortBy is stable.
      tabsToRender = sortBy(tabs, (tab) => {
          const nurl = tab.url?.normalized;
          const page = nurl ? normalizedUrlToPage[nurl] : undefined;
          if (!page) return 0; // Or generic value
          return pageSortOrderMap[sortOrder](page);
      });
  }

  return (
    <div
      style={{
        border: '1px solid',
        margin: '0.5rem 0.5rem 0.5rem 0.5rem',
        borderColor: 'rgb(50, 56, 62)',
      }}
    >
      <WindowTabListHeader accessTime={window.accessTime} tabs={tabs} urls={urls} />

      {tabsToRender &&
        tabsToRender.map((tab) => {
          const normalizedUrl = tab.url?.normalized;
          const page = normalizedUrl ? normalizedUrlToPage[normalizedUrl] : undefined;
          if (!page) {
            // OK; this can happen during attach (??)
            // console.error('No page found for tab: ', tab, normalizedUrlToPage);
            return <div key={tab.id}></div>;
          }
          if (!filterPage(page, filter)) { 
            return <div key={tab.id}></div>;
          }
          return <PageRow key={tab.id} page={page} windowId={windowId} tabId={tab.id} />;
        })}
    </div>
  );
});

export default WindowTabList;
