import { useEffect, useMemo, useRef, useState } from 'react';
import { filterRevisions, toRelativePath } from '../../data/historyUtils';
import { findNodeById } from '../../data/treeUtils';
import { useFileTreeTab } from '../../context/FileTreeTabContext';
import { useServerData } from '../../context/ServerDataContext';
import { UserAvatar } from '../UserAvatar';
import { RevisionDetailModal } from '../modals/RevisionDetailModal';
import { HistoryGraphView } from './HistoryGraphView';

const ARROW_RIGHT = 'assets/arrow_right.svg';
const ARROW_DOWN = 'assets/arrow_down.svg';

export function HistoryPanel() {
  const [query, setQuery] = useState('');
  const [openRevision, setOpenRevision] = useState(null);
  // Set when the modal is opened from a graph card, so the modal pre-selects
  // the graphed file; list-row opens leave it null.
  const [modalPreselect, setModalPreselect] = useState(null);
  const {
    tab,
    activeSelection,
    requestGraphView,
    requestRollback,
    historyView,
    graphViewRequest,
    clearGraphViewRequest,
    fileHashes,
  } = useFileTreeTab();
  const { revisions, getUser, fileHistoryIndex } = useServerData();
  // Both trees carry their root id on the root node (server name for the
  // depot, the workspace folder path for the workspace).
  const rootId = activeSelection?.tree?.[0]?.id ?? null;

  // ---- Graph View target file ---------------------------------------------
  // Default: the last-clicked *file* row in the active tree (anchorId).
  // A one-shot request from the revision modal pins an explicit path —
  // possibly one deleted off the repo — until the user clicks another file.
  const anchorNode =
    activeSelection?.anchorId && activeSelection?.tree
      ? findNodeById(activeSelection.tree, activeSelection.anchorId)
      : null;
  const anchorPath =
    anchorNode?.type === 'file' && rootId ? toRelativePath(anchorNode.id, rootId) : null;

  const [pinnedPath, setPinnedPath] = useState(null);
  const graphSeq = useRef(0);
  useEffect(() => {
    if (!graphViewRequest || graphViewRequest.seq === graphSeq.current) return;
    graphSeq.current = graphViewRequest.seq;
    setPinnedPath(graphViewRequest.path);
    clearGraphViewRequest();
  }, [graphViewRequest, clearGraphViewRequest]);

  // Clicking a different file in the tree releases the pin.
  const prevAnchorPath = useRef(anchorPath);
  useEffect(() => {
    if (anchorPath !== prevAnchorPath.current) {
      prevAnchorPath.current = anchorPath;
      if (anchorPath) setPinnedPath(null);
    }
  }, [anchorPath]);

  const graphPath = pinnedPath ?? anchorPath;

  // ---- List view data -------------------------------------------------------
  const scoped = useMemo(() => {
    if (!activeSelection?.tree || !rootId) return revisions;
    return filterRevisions(
      revisions,
      activeSelection.selectedIds,
      rootId,
      activeSelection.tree
    );
  }, [activeSelection, rootId, revisions]);

  const filtered = useMemo(() => {
    const q = query.toLowerCase().trim();
    if (!q) return scoped;
    return scoped.filter((r) => {
      const user = getUser(r.author);
      return (
        r.description.toLowerCase().includes(q) ||
        r.author.toLowerCase().includes(q) ||
        user.displayName.toLowerCase().includes(q) ||
        String(r.revision).includes(q)
      );
    });
  }, [query, scoped]);

  const openEntry = openRevision != null ? filtered.find((r) => r.revision === openRevision) ?? revisions.find((r) => r.revision === openRevision) : null;

  const openFromGraph = (revision) => {
    setModalPreselect(graphPath ? [graphPath] : null);
    setOpenRevision(revision);
  };

  const closeModal = () => {
    setOpenRevision(null);
    setModalPreselect(null);
  };

  const fileHistory = graphPath ? fileHistoryIndex.get(graphPath) ?? null : null;
  const serverHeadHash = graphPath ? fileHashes.serverHashes.get(graphPath) ?? null : null;
  const syncedHash = graphPath ? fileHashes.syncedHashes.get(graphPath) ?? null : null;

  return (
    <div className="history-container">
      {historyView === 'graph' ? (
        <HistoryGraphView
          fileHistory={fileHistory}
          relativePath={graphPath}
          serverHeadHash={serverHeadHash}
          syncedHash={syncedHash}
          onOpenRevision={openFromGraph}
        />
      ) : (
        <>
          <div className="history-table-wrap">
            <table className="history-table">
              <thead>
                <tr>
                  <th className="col-revision">Revision</th>
                  <th className="col-date">Date submitted</th>
                  <th className="col-author">Submitted by</th>
                  <th className="col-description">Description</th>
                </tr>
              </thead>
              <tbody>
                {filtered.map((r, i) => {
                  const user = getUser(r.author);
                  const isOpen = openRevision === r.revision;
                  return (
                    <tr
                      key={r.revision}
                      className={`${i % 2 === 1 ? 'history-row--alt' : ''}${isOpen ? ' history-row--expanded' : ''}`}
                      onDoubleClick={() => setOpenRevision(r.revision)}
                    >
                      <td className="col-revision">
                        <div className="history-revision-cell">
                          <button
                            type="button"
                            className="history-revision-toggle"
                            aria-expanded={isOpen}
                            aria-label={isOpen ? 'Close revision details' : 'Open revision details'}
                            onClick={() => setOpenRevision(isOpen ? null : r.revision)}
                          >
                            <img
                              src={isOpen ? ARROW_DOWN : ARROW_RIGHT}
                              alt=""
                              className="history-revision-toggle-icon"
                            />
                          </button>
                          <span>{r.revision}</span>
                        </div>
                      </td>
                      <td className="col-date">{r.date}</td>
                      <td className="col-author">
                        <div className="history-author-cell">
                          <UserAvatar user={user} size={22} />
                          <span className="history-author-name">{user.displayName}</span>
                        </div>
                      </td>
                      <td className="col-description">{r.description}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
          <div className="history-footer">
            <img src="assets/search.svg" alt="" />
            <input
              className="history-search"
              type="text"
              placeholder="Search"
              value={query}
              onChange={(e) => setQuery(e.target.value)}
            />
          </div>
        </>
      )}

      {openEntry && (
        <RevisionDetailModal
          entry={openEntry}
          onClose={closeModal}
          onShowInGraphView={requestGraphView}
          onRollback={requestRollback}
          initialSelectedPaths={modalPreselect}
        />
      )}
    </div>
  );
}
