import React, { useState, useEffect, useCallback } from 'react';
import { useLiveQuery } from 'dexie-react-hooks';
import {
  CssBaseline,
  CssVarsProvider,
  Sheet,
  Typography,
  Stack,
  Divider,
} from '@mui/joy';
import { db } from '../db/db';
import { addTag, removeTag } from '../db/pages';
import { fetchTagNames } from '../db/tags';
import { normalizeUrl } from '../chrome/normalizeUrl';
import { shouldIgnore } from '../db/urlNormalizationPrefs';
import { loadPrefsFromDB } from '../db/prefsLoader';
import { CustomTagSelector } from '../main/tagSelector/CustomTagSelector';
import { TagAttachment } from '../main/tagSelector/tag_utils';
import { SystemTags } from '../db/constants';
import '@fontsource/inter';
import './Sidebar.less';

// Initialize prefs so that shouldIgnore works correctly
loadPrefsFromDB();

const Sidebar = () => {
  const [currentUrl, setCurrentUrl] = useState<string | null>(null);
  const [tabTitle, setTabTitle] = useState<string | undefined>(undefined);
  const [tabFavIcon, setTabFavIcon] = useState<string | undefined>(undefined);

  const updateCurrentTab = useCallback(() => {
    chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
      const tab = tabs[0];
      if (tab?.url) {
        try {
          const nurl = normalizeUrl(tab.url);
          if (!shouldIgnore(nurl.normalized)) {
            setCurrentUrl(nurl.normalized);
            setTabTitle(tab.title);
            setTabFavIcon(tab.favIconUrl ?? undefined);
            return;
          }
        } catch {
          // ignore un-normalizable URLs
        }
      }
      setCurrentUrl(null);
      setTabTitle(undefined);
      setTabFavIcon(undefined);
    });
  }, []);

  useEffect(() => {
    updateCurrentTab();

    const handleActivated = () => updateCurrentTab();
    const handleUpdated = (
      _tabId: number,
      changeInfo: chrome.tabs.TabChangeInfo
    ) => {
      if (changeInfo.url !== undefined || changeInfo.title !== undefined) {
        updateCurrentTab();
      }
    };

    chrome.tabs.onActivated.addListener(handleActivated);
    chrome.tabs.onUpdated.addListener(handleUpdated);

    return () => {
      chrome.tabs.onActivated.removeListener(handleActivated);
      chrome.tabs.onUpdated.removeListener(handleUpdated);
    };
  }, [updateCurrentTab]);

  // Fetch the tracked page from IndexedDB
  const page = useLiveQuery(
    () => (currentUrl ? db.pages.get(currentUrl) : undefined),
    [currentUrl]
  );

  // All tag names for the add-tag autocomplete list
  const tagOptions = (useLiveQuery(fetchTagNames) ?? []) as string[];

  // Applied human tags (excluding system tags like #stash, #flag, etc.)
  const appliedTags: TagAttachment[] = (page?.humanTags ?? [])
    .filter((t) => !SystemTags.includes(t))
    .map((t) => ({ name: t, humanEdit: true, inferenceStrength: 1, proportion: 1 }));

  // Suggested tags: aggregate tags from URL-graph adjacent pages that aren't already applied
  const suggestedTags = useLiveQuery(async () => {
    if (!page) return [];
    const appliedSet = new Set(page.humanTags ?? []);
    const adjacentUrls = [
      ...(page.openerUrls ?? []),
      ...(page.openedUrls ?? []),
      ...(page.timeAdjacentUrls ?? []),
    ];
    if (adjacentUrls.length === 0) return [];

    const adjacentPages = await db.pages.bulkGet(adjacentUrls);
    const tagCounts: Record<string, number> = {};
    for (const p of adjacentPages) {
      if (!p) continue;
      for (const tag of p.humanTags ?? []) {
        if (!appliedSet.has(tag) && !SystemTags.includes(tag)) {
          tagCounts[tag] = (tagCounts[tag] || 0) + 1;
        }
      }
    }

    return Object.entries(tagCounts)
      .sort((a, b) => b[1] - a[1])
      .slice(0, 10)
      .map(([name, count]) => ({
        name,
        humanEdit: true,
        inferenceStrength: 1,
        proportion: Math.min(1, count / adjacentUrls.length),
      }));
  }, [page]);

  const handleAdd = (tag: string) => {
    if (tag && currentUrl) addTag([currentUrl], tag);
  };

  const handleRemove = (tag: string) => {
    if (tag && currentUrl) removeTag([currentUrl], tag);
  };

  const noop = () => {};

  const displayTitle = tabTitle ?? page?.title ?? currentUrl ?? '';

  return (
    <CssVarsProvider defaultMode="dark" disableNestedContext>
      <CssBaseline />
      <Sheet className="sidebar-root">
        {/* Header */}
        <Stack
          direction="row"
          alignItems="center"
          sx={{
            px: 1.5,
            py: 1,
            borderBottom: '1px solid',
            borderColor: 'divider',
            flexShrink: 0,
          }}
        >
          <Typography level="title-sm" sx={{ fontWeight: 'bold', color: 'primary.400' }}>
            Tabvana
          </Typography>
        </Stack>

        {currentUrl ? (
          <Stack
            direction="column"
            spacing={1.5}
            className="sidebar-scroll"
            sx={{ p: 1.5 }}
          >
            {/* Page info */}
            <Stack direction="row" alignItems="flex-start" spacing={1}>
              {tabFavIcon && (
                <img
                  src={tabFavIcon}
                  width={14}
                  height={14}
                  style={{ flexShrink: 0, marginTop: 2, borderRadius: 2 }}
                />
              )}
              <Typography
                level="body-xs"
                sx={{ wordBreak: 'break-word', color: 'text.secondary' }}
              >
                {displayTitle}
              </Typography>
            </Stack>

            <Divider />

            {/* Applied tags */}
            <Typography
              level="body-xs"
              sx={{
                fontWeight: 'bold',
                color: 'text.secondary',
                letterSpacing: '0.05em',
              }}
            >
              APPLIED TAGS
            </Typography>
            <CustomTagSelector
              options={tagOptions}
              attachments={appliedTags}
              onAdd={handleAdd}
              onDelete={handleRemove}
              onClickTag={noop}
              onDoubleClickTag={noop}
              multiSelect={true}
            />

            {/* Suggested tags (from URL-graph neighbors) */}
            {(suggestedTags?.length ?? 0) > 0 && (
              <>
                <Divider />
                <Typography
                  level="body-xs"
                  sx={{
                    fontWeight: 'bold',
                    color: 'text.tertiary',
                    letterSpacing: '0.05em',
                  }}
                >
                  SUGGESTED TAGS
                </Typography>
                <CustomTagSelector
                  options={tagOptions}
                  attachments={suggestedTags ?? []}
                  onAdd={handleAdd}
                  onDelete={handleRemove}
                  onClickTag={noop}
                  onDoubleClickTag={noop}
                  multiSelect={true}
                  hideAddButton={true}
                  proposed={true}
                />
              </>
            )}
          </Stack>
        ) : (
          <Stack sx={{ p: 2 }}>
            <Typography level="body-sm" sx={{ color: 'text.tertiary' }}>
              No trackable page is active.
            </Typography>
          </Stack>
        )}
      </Sheet>
    </CssVarsProvider>
  );
};

export default Sidebar;
