import { useEffect, useRef, useState } from 'react'
import { Timeline } from './components/timeline/Timeline'
import { DuplicatesView } from './components/duplicates/DuplicatesView'
import { MapView } from './components/map/MapView'
import { MemoriesView } from './components/memories/MemoriesView'
import { TagsView } from './components/tags/TagsView'
import { ColorsView } from './components/colors/ColorsView'
import { RatedView } from './components/rated/RatedView'
import { LeftSidebar } from './components/layout/LeftSidebar'
import { RightSidebar } from './components/layout/RightSidebar'
import { TopBar } from './components/layout/TopBar'
import { ScanProgress } from './components/ScanProgress'
import { ToastContainer } from './components/ToastContainer'
import { KeyboardHints } from './components/KeyboardHints'
import { PreviewView } from './components/preview/PreviewView'
import { FilterBar } from './components/filter/FilterBar'
import { DiscardActionBar } from './components/discard/DiscardActionBar'
import { SettingsPage } from './components/dialogs/SettingsDialog'
import { usePhotoStore } from './store/photoStore'
import { useFilterStore } from './store/filterStore'
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts'
import { useFilterUrlSync } from './hooks/useFilterUrlSync'
import { usePhotosQuery } from './hooks/usePhotosQuery'
import { AuthProvider, useAuth } from './contexts/AuthContext'
import { LoginPage } from './components/auth/LoginPage'
import { SetupPage } from './components/auth/SetupPage'
import { OidcCallback } from './components/auth/OidcCallback'
import { TooltipProvider } from '@/components/ui/tooltip'

function MainApp() {
  const [leftSidebarOpen, setLeftSidebarOpen] = useState(true)
  const [rightSidebarOpen, setRightSidebarOpen] = useState(true)
  // Respect the user's manual collapse of the metadata panel. Once they
  // close it explicitly (via `i` hotkey or the sidebar toggle button),
  // selecting a new photo should NOT force it back open. Cleared when
  // they open it manually again.
  const rightCollapsedByUser = useRef(false)
  const viewMode = usePhotoStore((state) => state.viewMode)
  const activePhotoId = usePhotoStore((state) => state.activePhotoId)
  const currentSection = useFilterStore((s) => s.currentSection)

  // Close the metadata panel when the user switches between sections so
  // it doesn't carry over a now-irrelevant selection. It re-opens once a
  // photo gains focus in the new section (effect below).
  const prevSectionRef = useRef(currentSection)
  useEffect(() => {
    if (prevSectionRef.current !== currentSection) {
      prevSectionRef.current = currentSection
      setRightSidebarOpen(false)
    }
  }, [currentSection])

  useEffect(() => {
    if (!activePhotoId) {
      setRightSidebarOpen(false)
      return
    }
    // User explicitly collapsed the panel — don't undo that just because
    // they picked a different photo.
    if (rightCollapsedByUser.current) return
    setRightSidebarOpen(true)
  }, [activePhotoId])

  const toggleRightSidebar = () => {
    setRightSidebarOpen((prev) => {
      const next = !prev
      rightCollapsedByUser.current = !next
      return next
    })
  }

  // Bidirectional sync of filter store with URL query params.
  useFilterUrlSync()

  // Subscribe to the same photos query the Timeline uses, so the keyboard
  // "open preview on first photo" path can read from the live cache regardless
  // of what filter key it's stored under.
  const { data: allPhotos } = usePhotosQuery()

  // Set up global keyboard shortcuts. Prefer the Timeline's published
  // visible sequence (which respects per-month ordering) over the raw
  // backend list — otherwise "Space on a blank selection" would open
  // the globally first photo, which isn't what the user sees at the
  // top-left of the grid.
  useKeyboardShortcuts({
    onToggleLeftSidebar: () => setLeftSidebarOpen(!leftSidebarOpen),
    onToggleRightSidebar: toggleRightSidebar,
    getFirstPhotoId: () =>
      usePhotoStore.getState().visiblePhotoIds[0] ??
      allPhotos?.[0]?.id ??
      null,
  })

  // Settings page is a full-page section — hide filter bar, right sidebar,
  // and keyboard hints when it's active.
  const isSettings = currentSection === 'settings'

  // Right sidebar stays open by default and shows whatever's selected
  // (or an empty state if nothing is). User can still toggle it manually.
  const showRightSidebar = rightSidebarOpen && !isSettings

  return (
    <TooltipProvider delayDuration={300}>
    <div className="flex flex-col h-screen bg-bg text-text">
      <TopBar />

      <div className="flex flex-1 overflow-hidden">
        {/* Left Sidebar */}
        <div
          className={`transition-all duration-200 ${
            leftSidebarOpen ? 'w-60' : 'w-0'
          } overflow-hidden border-r border-border bg-surface`}
        >
          <LeftSidebar />
        </div>

        {/* Main column — filter bar, discard bar, timeline. Lives to the
         *  right of the left sidebar so the filter row doesn't bleed
         *  across the sidebar. relative so the KeyboardHints overlay
         *  centers against this column, not the viewport. */}
        <div className="relative flex min-w-0 flex-1 flex-col">
          {!isSettings && (
            <FilterBar
              leftSidebarOpen={leftSidebarOpen}
              rightSidebarOpen={showRightSidebar}
              onToggleLeftSidebar={() => setLeftSidebarOpen(!leftSidebarOpen)}
              onToggleRightSidebar={toggleRightSidebar}
            />
          )}
          {!isSettings && <DiscardActionBar />}
          <div className="flex-1 overflow-auto">
            {currentSection === 'settings' ? (
              <SettingsPage />
            ) : currentSection === 'map' ? (
              <MapView />
            ) : currentSection === 'memories' ? (
              <MemoriesView />
            ) : currentSection === 'duplicates' ? (
              <DuplicatesView />
            ) : currentSection === 'tags' ? (
              <TagsView />
            ) : currentSection === 'colors' ? (
              <ColorsView />
            ) : currentSection === 'rated' ? (
              <RatedView />
            ) : (
              <Timeline />
            )}
          </div>
          {!isSettings && viewMode !== 'preview' && <KeyboardHints />}
        </div>

        {/* Right Sidebar */}
        <div
          className={`transition-all duration-200 ${
            showRightSidebar ? 'w-72' : 'w-0'
          } overflow-hidden border-l border-border bg-surface`}
        >
          <RightSidebar />
        </div>
      </div>

      {/* Scan Progress Indicator */}
      <ScanProgress />

      {/* Toast Notifications */}
      <ToastContainer />

      {/* Preview overlay — covers TopBar when active */}
      {viewMode === 'preview' && <PreviewView />}

    </div>
    </TooltipProvider>
  )
}

/** Auth-gated shell: shows setup, login, or the main app. */
function App() {
  return (
    <AuthProvider>
      <AuthGate />
    </AuthProvider>
  )
}

function AuthGate() {
  const { user, isLoading, needsSetup } = useAuth()

  // OIDC callback lands on /auth/callback — handle it even while
  // isLoading, so the callback page can adopt tokens and transition
  // straight to MainApp without flashing the login screen.
  if (window.location.pathname.startsWith('/auth/callback')) {
    return <OidcCallback />
  }

  if (isLoading) {
    return (
      <div className="flex min-h-screen items-center justify-center bg-bg">
        <div className="text-text-muted">Loading&hellip;</div>
      </div>
    )
  }

  if (needsSetup) return <SetupPage />
  if (!user) return <LoginPage />
  return <MainApp />
}

export default App