import React, { useMemo, useState, useEffect, useCallback, useRef } from "react";
import { SessionList } from "./components/SessionList";
import { SessionViewer } from "./components/SessionViewer";
import { FilterPanel } from "./components/FilterPanel";
import { SearchBar } from "./components/SearchBar";
import { SearchMinimap } from "./components/SearchMinimap";
import { ExportButton } from "./components/ExportButton";
import { useSession } from "./hooks/useSession";
import { useFilters } from "./hooks/useFilters";


export function App() {
  const {
    sessions,
    sessionsLoading,
    currentSession,
    sessionLoading,
    loadSession,
  } = useSession();

  const filters = useFilters();

  const filteredMessages = useMemo(() => {
    if (!currentSession) return [];
    return filters.filterMessages(currentSession.messages);
  }, [currentSession, filters.filterMessages]);

  // Track which filtered-message indices match the search query
  const matchIndices = useMemo(() => {
    if (!filters.searchQuery) return [];
    const lq = filters.searchQuery.toLowerCase();
    return filteredMessages.reduce<number[]>((acc, msg, i) => {
      if (
        msg.content.toLowerCase().includes(lq) ||
        (msg.toolInput && msg.toolInput.toLowerCase().includes(lq))
      ) {
        acc.push(i);
      }
      return acc;
    }, []);
  }, [filteredMessages, filters.searchQuery]);

  const matchCount = matchIndices.length;

  // Which match is currently focused (index into matchIndices)
  const [currentMatchPosition, setCurrentMatchPosition] = useState(-1);

  // Reset to first match when search results change
  useEffect(() => {
    setCurrentMatchPosition(matchIndices.length > 0 ? 0 : -1);
  }, [matchIndices]);

  const goToNextMatch = useCallback(() => {
    if (matchIndices.length === 0) return;
    setCurrentMatchPosition((prev) =>
      prev < matchIndices.length - 1 ? prev + 1 : 0
    );
  }, [matchIndices.length]);

  const goToPrevMatch = useCallback(() => {
    if (matchIndices.length === 0) return;
    setCurrentMatchPosition((prev) =>
      prev > 0 ? prev - 1 : matchIndices.length - 1
    );
  }, [matchIndices.length]);

  const focusedMessageIndex =
    currentMatchPosition >= 0 ? matchIndices[currentMatchPosition] : -1;

  const visibleUuids = useMemo(
    () => filteredMessages.map((m) => m.uuid),
    [filteredMessages]
  );

  // Scroll tracking for minimap viewport indicator
  const scrollRef = useRef<HTMLDivElement>(null);
  const [viewportTop, setViewportTop] = useState(0);
  const [viewportHeight, setViewportHeight] = useState(1);

  const updateViewport = useCallback(() => {
    const el = scrollRef.current;
    if (!el || el.scrollHeight === 0) return;
    setViewportTop(el.scrollTop / el.scrollHeight);
    setViewportHeight(Math.min(el.clientHeight / el.scrollHeight, 1));
  }, []);

  useEffect(() => {
    const el = scrollRef.current;
    if (!el) return;
    el.addEventListener("scroll", updateViewport, { passive: true });
    // Initial measurement
    updateViewport();
    // Re-measure when content changes
    const ro = new ResizeObserver(updateViewport);
    ro.observe(el);
    return () => {
      el.removeEventListener("scroll", updateViewport);
      ro.disconnect();
    };
  }, [updateViewport]);

  // Re-measure when messages change (content size changes)
  useEffect(() => {
    updateViewport();
  }, [filteredMessages, updateViewport]);

  return (
    <div className="flex h-screen" style={{ background: "var(--color-canvas)" }}>
      {/* Sidebar */}
      <div className="w-80 flex-shrink-0 border-r border-border bg-surface-raised flex flex-col">
        <div className="px-5 py-4 border-b border-border" style={{ background: "linear-gradient(180deg, var(--color-surface-overlay) 0%, var(--color-surface-raised) 100%)" }}>
          <h1 className="text-heading font-semibold text-foreground tracking-tight">
            Session Viewer
          </h1>
          <p className="text-caption text-foreground-muted mt-0.5">
            Browse and export Claude sessions
          </p>
        </div>
        <div className="flex-1 overflow-y-auto">
          <SessionList
            sessions={sessions}
            loading={sessionsLoading}
            selectedId={currentSession?.id}
            onSelect={loadSession}
          />
        </div>
        <FilterPanel
          enabledCategories={filters.enabledCategories}
          onToggle={filters.toggleCategory}
          autoRedactEnabled={filters.autoRedactEnabled}
          onAutoRedactToggle={filters.setAutoRedactEnabled}
        />
      </div>

      {/* Main */}
      <div className="flex-1 flex flex-col min-w-0">
        <div className="glass flex items-center px-5 py-2.5 border-b border-border z-10">
          {/* Left spacer — mirrors right side width to keep search centered */}
          <div className="flex-1 min-w-0" />

          {/* Center — search bar + contextual redaction controls */}
          <div className="flex items-center gap-3 flex-shrink-0">
            <SearchBar
              query={filters.searchQuery}
              onQueryChange={filters.setSearchQuery}
              matchCount={matchCount}
              currentMatchPosition={currentMatchPosition}
              onNext={goToNextMatch}
              onPrev={goToPrevMatch}
            />
            {filters.selectedForRedaction.size > 0 && (
              <div className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-red-500/8 border border-red-500/15 animate-fade-in">
                <span className="text-caption text-red-400 font-medium tabular-nums whitespace-nowrap">
                  {filters.selectedForRedaction.size} selected
                </span>
                <button
                  onClick={filters.confirmRedaction}
                  className="btn btn-sm btn-danger"
                >
                  Redact
                </button>
                <button
                  onClick={filters.clearRedactionSelection}
                  className="btn btn-sm btn-ghost text-red-400/70 hover:text-red-300"
                >
                  Cancel
                </button>
              </div>
            )}
          </div>

          {/* Right — export button, right-justified */}
          <div className="flex-1 min-w-0 flex justify-end">
            {currentSession && (
              <ExportButton
                session={currentSession}
                visibleMessageUuids={visibleUuids}
                redactedMessageUuids={[...filters.redactedUuids]}
                autoRedactEnabled={filters.autoRedactEnabled}
              />
            )}
          </div>
        </div>
        {/* Scroll area wrapper — relative so minimap can position over the right edge */}
        <div className="flex-1 relative min-h-0">
          <div ref={scrollRef} className="h-full overflow-y-auto">
            <SessionViewer
              messages={filteredMessages}
              allMessages={currentSession?.messages || []}
              redactedUuids={filters.redactedUuids}
              loading={sessionLoading}
              searchQuery={filters.searchQuery}
              selectedForRedaction={filters.selectedForRedaction}
              onToggleRedactionSelection={filters.toggleRedactionSelection}
              autoRedactEnabled={filters.autoRedactEnabled}
              focusedIndex={focusedMessageIndex}
            />
          </div>
          <SearchMinimap
            matchIndices={matchIndices}
            totalMessages={filteredMessages.length}
            currentPosition={currentMatchPosition}
            onClickMatch={setCurrentMatchPosition}
            viewportTop={viewportTop}
            viewportHeight={viewportHeight}
          />
        </div>
      </div>
    </div>
  );
}
