import { useState, useEffect, useCallback } from 'react'
import styles from './App.module.css'
import TraceViewer from './components/TraceViewer'
import PhaseViewer from './components/PhaseViewer'
import HTTPRequestViewer from './components/httprequestviewer/HTTPRequestViewer'
import JavaScriptViewer from './components/javascriptviewer/JavaScriptViewer'
import RequestBreakdown from './components/RequestBreakdown'
import RequestDebugger from './components/RequestDebugger'
import TraceUpload from './components/TraceUpload'
import TraceSelector from './components/TraceSelector'
import { traceDatabase } from './utils/traceDatabase'
import { useDatabaseTraceData } from './hooks/useDatabaseTraceData'

type AppView = 'trace' | 'phases' | 'http' | 'js' | 'breakdown' | 'debug'
type AppMode = 'selector' | 'upload' | 'analysis'
type ThreeDView = 'network' | 'timeline' | null

// URL path utilities for /[traceid]/[view]/[3dview] routing
const updateUrlWithTraceId = (traceId: string | null, view: AppView = 'http', threeDView: ThreeDView = null) => {
  if (!traceId) {
    window.history.pushState({}, '', '/')
    return
  }
  
  const path = threeDView ? `/${traceId}/${view}/${threeDView}` : `/${traceId}/${view}`
  window.history.pushState({}, '', path)
}

const getUrlParams = () => {
  const path = window.location.pathname
  const segments = path.split('/').filter(Boolean) // Remove empty segments
  
  if (segments.length >= 3) {
    const traceId = segments[0]
    const view = segments[1] as AppView
    const threeDView = segments[2] as ThreeDView
    // Validate view and 3D view values
    const validViews: AppView[] = ['trace', 'phases', 'http', 'js', 'breakdown', 'debug']
    const validThreeDViews: (ThreeDView)[] = ['network', 'timeline']
    const validatedView = validViews.includes(view) ? view : 'http'
    const validatedThreeDView = validThreeDViews.includes(threeDView) ? threeDView : null
    return { traceId, view: validatedView, threeDView: validatedThreeDView }
  } else if (segments.length >= 2) {
    const traceId = segments[0]
    const view = segments[1] as AppView
    // Validate view is one of the allowed values
    const validViews: AppView[] = ['trace', 'phases', 'http', 'js', 'breakdown', 'debug']
    const validatedView = validViews.includes(view) ? view : 'http'
    return { traceId, view: validatedView, threeDView: null }
  } else if (segments.length === 1) {
    // Only trace ID provided, default to http view
    return { traceId: segments[0], view: 'http' as AppView, threeDView: null }
  }
  
  // Root path or invalid format
  return { traceId: null, view: 'http' as AppView, threeDView: null }
}

// Export utility functions for use in other components
export { getUrlParams, updateUrlWithTraceId, type ThreeDView }

function App() {
  const [mode, setMode] = useState<AppMode>('selector')
  const [currentView, setCurrentView] = useState<AppView>('http')
  const [selectedTraceId, setSelectedTraceId] = useState<string | null>(null)
  const [, setHasTraces] = useState<boolean>(false)
  const [dbInitialized, setDbInitialized] = useState(false)
  
  // Always call hooks at the top level
  const { traceData } = useDatabaseTraceData(selectedTraceId)

  // Handle browser back/forward navigation
  const handlePopState = useCallback(() => {
    const { traceId, view } = getUrlParams()
    if (traceId && traceId !== selectedTraceId) {
      setSelectedTraceId(traceId)
      setCurrentView(view)
      setMode('analysis')
      // Note: threeDView will be handled by HTTPRequestViewer component
    } else if (!traceId && selectedTraceId) {
      setSelectedTraceId(null)
      setMode('selector')
    }
  }, [selectedTraceId])

  useEffect(() => {
    initializeApp()
    
    // Listen for browser navigation (back/forward)
    window.addEventListener('popstate', handlePopState)
    return () => window.removeEventListener('popstate', handlePopState)
  }, [handlePopState])

  const initializeApp = async () => {
    try {
      // Initialize the database
      await traceDatabase.init()
      setDbInitialized(true)
      
      // Check if we have any traces
      const traces = await traceDatabase.getAllTraces()
      setHasTraces(traces.length > 0)
      
      // Check URL for existing trace parameter
      const { traceId, view } = getUrlParams()
      if (traceId && traces.some(t => t.id === traceId)) {
        // Valid trace ID in URL, load it
        setSelectedTraceId(traceId)
        setCurrentView(view)
        setMode('analysis')
        // Note: threeDView will be handled by HTTPRequestViewer component
      } else if (traceId) {
        // Invalid trace ID in URL, clear it and show selector
        window.history.replaceState({}, '', '/')
        setMode(traces.length > 0 ? 'selector' : 'upload')
      } else if (traces.length === 0) {
        // No traces, show upload screen
        setMode('upload')
      } else {
        // Has traces, show selector
        setMode('selector')
      }
    } catch (error) {
      console.error('Failed to initialize database:', error)
      setMode('upload') // Fallback to upload mode
      setDbInitialized(true)
    }
  }

  const handleTraceSelect = (traceId: string) => {
    setSelectedTraceId(traceId)
    setCurrentView('http') // Default to HTTP view
    setMode('analysis')
    updateUrlWithTraceId(traceId, 'http', null)
  }

  const handleUploadSuccess = (traceId: string) => {
    setSelectedTraceId(traceId)
    setCurrentView('http')
    setMode('analysis')
    setHasTraces(true)
    updateUrlWithTraceId(traceId, 'http', null)
  }

  const handleBackToSelector = () => {
    setSelectedTraceId(null)
    setMode('selector')
    window.history.pushState({}, '', '/')
  }

  const handleUploadNew = () => {
    setMode('upload')
  }

  if (!dbInitialized) {
    return (
      <div style={{
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        minHeight: '100vh',
        fontFamily: 'system-ui, sans-serif'
      }}>
        <div>Initializing database...</div>
      </div>
    )
  }

  if (mode === 'upload') {
    return <TraceUpload onUploadSuccess={handleUploadSuccess} />
  }

  if (mode === 'selector') {
    return (
      <TraceSelector 
        onTraceSelect={handleTraceSelect}
        onUploadNew={handleUploadNew}
      />
    )
  }

  // Analysis mode - show the main interface
  return (
    <>
      <div className={styles.mainApp}>
        <div className={styles.appHeader}>
          <div className={styles.headerLeft}>
            <button
              className={styles.backButton}
              onClick={handleBackToSelector}
            >
              ← Back to Traces
            </button>
            <h1 className={styles.appTitle}>Performance Trace Analysis</h1>
          </div>
          <nav className={styles.nav}>
            <button 
              className={`${styles.navButton} ${currentView === 'trace' ? styles.active : ''}`}
              onClick={() => {
                setCurrentView('trace')
                updateUrlWithTraceId(selectedTraceId, 'trace', null)
              }}
            >
              Trace Stats
            </button>
            <button 
              className={`${styles.navButton} ${currentView === 'phases' ? styles.active : ''}`}
              onClick={() => {
                setCurrentView('phases')
                updateUrlWithTraceId(selectedTraceId, 'phases', null)
              }}
            >
              Phase Events
            </button>
            <button 
              className={`${styles.navButton} ${currentView === 'http' ? styles.active : ''}`}
              onClick={() => {
                setCurrentView('http')
                updateUrlWithTraceId(selectedTraceId, 'http', null)
              }}
            >
              HTTP Requests
            </button>
            <button 
              className={`${styles.navButton} ${currentView === 'js' ? styles.active : ''}`}
              onClick={() => {
                setCurrentView('js')
                updateUrlWithTraceId(selectedTraceId, 'js', null)
              }}
            >
              JavaScript
            </button>
            <button 
              className={`${styles.navButton} ${currentView === 'breakdown' ? styles.active : ''}`}
              onClick={() => {
                setCurrentView('breakdown')
                updateUrlWithTraceId(selectedTraceId, 'breakdown', null)
              }}
            >
              Request Breakdown
            </button>
            <button 
              className={`${styles.navButton} ${currentView === 'debug' ? styles.active : ''}`}
              onClick={() => {
                setCurrentView('debug')
                updateUrlWithTraceId(selectedTraceId, 'debug', null)
              }}
            >
              Request Debug
            </button>
          </nav>
        </div>

        {currentView === 'trace' && (
          <TraceViewer traceId={selectedTraceId} />
        )}

        {currentView === 'phases' && (
          <PhaseViewer traceId={selectedTraceId} />
        )}

        {currentView === 'http' && (
          <HTTPRequestViewer traceId={selectedTraceId} />
        )}

        {currentView === 'js' && (
          <JavaScriptViewer traceId={selectedTraceId} />
        )}

        {currentView === 'breakdown' && (
          <RequestBreakdown traceId={selectedTraceId} />
        )}

        {currentView === 'debug' && traceData && (
          <RequestDebugger traceEvents={traceData.traceEvents} />
        )}
      </div>
    </>
  )
}

export default App
