import { useEffect } from 'react'
import { SignedIn, SignedOut, useAuth } from '@clerk/clerk-react'
import { useRef, useState, useCallback } from 'react'
import { get, setAuthToken, setTokenRefresh } from './api/client.js'
import { sendChatMessage, sendSlashCommand } from './api/chat.js'
import { useConversations } from './hooks/useConversations.js'
import { useMessages } from './hooks/useMessages.js'
import { useDocuments } from './hooks/useDocuments.js'
import { useImageUpload } from './hooks/useImageUpload.js'
import { useFullscreenImage } from './hooks/useFullscreenImage.js'
import { useClickOutside } from './hooks/useClickOutside.js'
import { DEFAULT_TOOLS } from './utils/constants.js'
import SlashCommandsDropdown, { parseSlashCommand } from './components/chat/SlashCommandsDropdown.jsx'
import Header from './components/layout/Header.jsx'
import Sidebar from './components/layout/Sidebar.jsx'
import MessageList from './components/chat/MessageList.jsx'
import FullscreenImage from './components/chat/FullscreenImage.jsx'
import ToolMenu from './components/documents/ToolMenu.jsx'
import ErrorBoundary from './components/common/ErrorBoundary.jsx'
import SignInPage from './components/auth/SignInPage.jsx'

// Visually hidden style for file inputs — keeps them in the DOM for mobile browsers
const hiddenInputStyle = {
  position: 'fixed',
  top: '-99999px',
  left: '-99999px',
  opacity: 0,
  pointerEvents: 'none',
  width: '1px',
  height: '1px',
}

function AppContent() {
  // Hooks
  const {
    conversations,
    setConversations,
    activeId,
    setActiveId,
    refreshConversations,
    createNewChat,
    deleteChat,
    updateTitle,
  } = useConversations()

  const {
    messages,
    setMessages,
    isThinking,
    setIsThinking,
    statusText,
    setStatusText,
    sendMessage,
  } = useMessages({ activeId, refreshConversations })

  const {
    documents,
    selectedDocuments,
    useRag,
    setUseRag,
    uploading,
    uploadSuccess,
    uploadError,
    uploadDocument,
    deleteDocument,
    toggleDocument,
    clearSelection,
  } = useDocuments(activeId)

  const {
    uploadedImage,
    imageAnalysis,
    imageUrl,
    analyzingImage,
    clearImage,
    clearImageState,
    handleImageUpload,
    handlePaste,
  } = useImageUpload()

  const { fullscreenImage, openFullscreen, closeFullscreen } = useFullscreenImage()

  // Local UI state
  const [sidebarOpen, setSidebarOpen] = useState(false)
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false)
  const [inputValue, setInputValue] = useState('')
  const [availableTools, setAvailableTools] = useState(DEFAULT_TOOLS)
  const [selectedTools, setSelectedTools] = useState([])
  const [showTools, setShowTools] = useState(false)
  const [showSlashCommands, setShowSlashCommands] = useState(false)

  const toolsRef = useRef(null)
  const imageInputRef = useRef(null)
  const fileInputRef = useRef(null)
  const textareaRef = useRef(null)

  // Clear image state on conversation switch
  useEffect(() => {
    clearImageState()
  }, [activeId, clearImageState])

  // Load available tools on mount
  useEffect(() => {
    get('/api/tools')
      .then((data) => setAvailableTools(data.tools || DEFAULT_TOOLS))
      .catch(() => {})
  }, [])

  // Click outside to close tools menu
  useClickOutside(toolsRef, () => setShowTools(false), [fileInputRef, imageInputRef])

  const handleSlashCommand = useCallback(async (cmd, topicOverride) => {
    if (!activeId) return

    const topic = topicOverride ?? (inputValue.slice(cmd.id.length + 1).trim())

    const userMsg = { id: `user-${Date.now()}`, role: 'user', content: `/${cmd.id} ${topic}` }
    setMessages((prev) => [...prev, userMsg])

    setInputValue('')
    setIsThinking(true)
    setStatusText(cmd.id === 'summarize' ? 'Summarizing conversation...' : 'Researching...')
    setShowTools(false)

    try {
      const data = await sendSlashCommand(cmd.id, activeId, topic)

      const assistantMsg = {
        id: `assistant-${Date.now()}`,
        role: 'assistant',
        content: data.error ? data.error : (data.answer || 'No response'),
      }
      setMessages((prev) => [...prev, assistantMsg])
    } catch (error) {
      const assistantMsg = {
        id: `assistant-${Date.now()}`,
        role: 'assistant',
        content: `${error.message}`,
      }
      setMessages((prev) => [...prev, assistantMsg])
    }

    setIsThinking(false)
    setStatusText('')
    refreshConversations()
  }, [activeId, inputValue, messages, refreshConversations])

  const handleSend = useCallback(() => {
    // Check if this is a slash command
    const parsed = parseSlashCommand(inputValue)
    if (parsed && parsed.matched) {
      handleSlashCommand(parsed.matched)
      return
    }

    sendMessage({
      inputValue,
      uploadedImage,
      imageAnalysis,
      imageUrl,
      selectedTools,
      selectedDocuments,
      useRag,
      setInputValue,
      clearImageState,
      setShowTools,
    })
  }, [inputValue, uploadedImage, imageAnalysis, imageUrl, selectedTools, selectedDocuments, useRag, sendMessage, handleSlashCommand, clearImageState])

  const handleKeyDown = useCallback((event) => {
    if (event.key === 'Enter' && !event.shiftKey) {
      event.preventDefault()
      handleSend()
    }
  }, [handleSend])

  const handleNewChat = useCallback(() => {
    createNewChat()
    setSidebarOpen(false)
  }, [createNewChat])

  const handleSelectConversation = useCallback((convId) => {
    setActiveId(convId)
    setSidebarOpen(false)
  }, [setActiveId])

  return (
    <ErrorBoundary>
    <div className="app-shell">
      <FullscreenImage src={fullscreenImage} onClose={closeFullscreen} />

      <Sidebar
        conversations={conversations}
        activeId={activeId}
        onSelectConv={handleSelectConversation}
        onNewChat={handleNewChat}
        onEditTitle={updateTitle}
        onDeleteChat={deleteChat}
        sidebarOpen={sidebarOpen}
        sidebarCollapsed={sidebarCollapsed}
        onToggleCollapse={() => setSidebarCollapsed((prev) => !prev)}
        onClose={() => setSidebarOpen(false)}
      />

      <main className="chat-panel">
        <Header onToggleSidebar={() => setSidebarOpen(true)} />

        <MessageList
          messages={messages}
          isThinking={isThinking}
          statusText={statusText}
          onImageClick={openFullscreen}
        />

        {/* Visually hidden file inputs — uses clip pattern instead of display:none for mobile browser compatibility */}
        <input
          ref={imageInputRef}
          id="img-upload-input"
          type="file"
          accept="image/*"
          onChange={handleImageUpload}
          style={hiddenInputStyle}
          tabIndex={-1}
        />
        <input
          ref={fileInputRef}
          id="doc-upload-input"
          type="file"
          accept="application/pdf,text/plain,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
          onChange={async (e) => {
            const file = e.target.files?.[0]
            if (file) {
              await uploadDocument(file)
              e.target.value = ''
            }
          }}
          style={hiddenInputStyle}
          tabIndex={-1}
        />

        <footer className="composer" style={{ position: 'relative', zIndex: 100, flexDirection: 'column' }}>
          {/* Slash commands dropdown - positioned above the composer */}
          <div style={{ position: 'absolute', bottom: '100%', left: 0, right: 0, height: 0 }}>
            {showSlashCommands && (
              <SlashCommandsDropdown
                inputValue={inputValue}
                onSelect={(cmd) => {
                  setInputValue('/' + cmd.id + ' ')
                  setShowSlashCommands(false)
                  setTimeout(() => textareaRef.current?.focus(), 0)
                }}
                onClose={() => setShowSlashCommands(false)}
              />
            )}
          </div>
          <div style={{ display: 'flex', alignItems: 'flex-end', gap: '10px', width: '100%' }}>
            {/* Tools + button */}
            <div style={{ position: 'relative' }} ref={toolsRef}>
              <button
                className={`tool-btn ${showTools ? 'active' : ''} ${selectedTools.length > 0 ? 'has-selection' : ''}`}
                onClick={() => setShowTools(!showTools)}
                aria-label="Add attachment"
                style={{ flexShrink: 0 }}
              >
                <span className="tool-btn-icon">+</span>
                {selectedTools.length > 0 && !showTools && (
                  <span className="tool-badge">{selectedTools.length}</span>
                )}
              </button>

              <ToolMenu
                showTools={showTools}
                uploading={uploading}
                uploadSuccess={uploadSuccess}
                uploadError={uploadError}
                documents={documents}
                selectedDocuments={selectedDocuments}
                onToggleDocument={toggleDocument}
                onDeleteDocument={deleteDocument}
                onClearSelection={clearSelection}
                useRag={useRag}
                onToggleRag={setUseRag}
                availableTools={availableTools}
                selectedTools={selectedTools}
                onToggleTool={(toolName) => {
                  setSelectedTools((prev) =>
                    prev.includes(toolName)
                      ? prev.filter((t) => t !== toolName)
                      : [...prev, toolName],
                  )
                }}
                onClearTools={() => setSelectedTools([])}
                toolsRef={toolsRef}
              />
            </div>

            {/* Input area */}
            <div style={{
              flex: 1,
              display: 'flex',
              flexDirection: 'column',
              borderRadius: '14px',
              border: '1px solid #e5e7eb',
              background: '#fff',
              overflow: 'hidden',
            }}>
              {(uploadedImage || analyzingImage) && (
                <div style={{ padding: '8px 12px', borderBottom: '1px solid #f3f4f6', background: '#fafafa' }}>
                  {analyzingImage ? (
                    <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                      <span style={{ fontSize: '0.8rem', animation: 'spin 1s linear infinite' }}>⟳</span>
                      <span style={{ fontSize: '0.85rem', color: '#6b7280' }}>Analyzing image...</span>
                    </div>
                  ) : uploadedImage && (
                    <div style={{ position: 'relative', display: 'inline-block' }}>
                      <img
                        src={uploadedImage}
                        alt="Attached"
                        style={{ width: '48px', height: '48px', borderRadius: '6px', border: '1px solid #e5e7eb', objectFit: 'cover' }}
                      />
                      <button
                        onClick={clearImage}
                        style={{
                          position: 'absolute',
                          top: '-6px',
                          right: '-6px',
                          background: '#111827',
                          color: '#fff',
                          border: 'none',
                          borderRadius: '50%',
                          width: '18px',
                          height: '18px',
                          cursor: 'pointer',
                          fontSize: '0.7rem',
                          padding: 0,
                          display: 'flex',
                          alignItems: 'center',
                          justifyContent: 'center',
                        }}
                        title="Remove image"
                      >
                        ✕
                      </button>
                    </div>
                  )}
                </div>
              )}

              <textarea
                ref={textareaRef}
                placeholder="Ask something..."
                value={inputValue}
                onChange={(event) => {
                  const val = event.target.value
                  setInputValue(val)
                  const parsed = parseSlashCommand(val)
                  if (val.startsWith('/') && (!parsed || !parsed.matched)) {
                    setShowSlashCommands(true)
                  } else {
                    setShowSlashCommands(false)
                  }
                }}
                onKeyDown={(e) => {
                  if (e.key === 'Escape' && showSlashCommands) {
                    setShowSlashCommands(false)
                    e.preventDefault()
                    return
                  }
                  if (e.key === 'Enter' && showSlashCommands) {
                    e.preventDefault()
                    return
                  }
                  handleKeyDown(e)
                }}
                onPaste={handlePaste}
                rows={1}
                style={{
                  width: '100%',
                  minHeight: '44px',
                  resize: 'none',
                  border: 'none',
                  padding: '12px 14px',
                  fontFamily: 'var(--font-ui)',
                  fontSize: '1rem',
                  color: 'var(--text)',
                  outline: 'none',
                  background: 'transparent',
                }}
              />
            </div>

            <button
              className="primary"
              onClick={handleSend}
              disabled={isThinking}
              aria-label="Send"
              style={{
                background: '#111827',
                color: '#ffffff',
                padding: '0 18px',
                height: '44px',
                borderRadius: '8px',
                fontWeight: 600,
                border: 'none',
                cursor: isThinking ? 'not-allowed' : 'pointer',
                opacity: isThinking ? 0.6 : 1,
                flexShrink: 0,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                fontSize: '1rem',
              }}
            >
              Send
            </button>
          </div>
        </footer>
      </main>

      {sidebarOpen && <div className="sidebar-backdrop" onClick={() => setSidebarOpen(false)} />}
    </div>
    </ErrorBoundary>
  )
}

function App() {
  const { isLoaded, isSignedIn, getToken } = useAuth()
  const [tokenReady, setTokenReady] = useState(false)

  useEffect(() => {
    if (!isLoaded) return
    setTokenReady(false)

    // Not signed in → no token needed, let SignedOut render
    if (!isSignedIn) {
      setTokenReady(true)
      return
    }

    let cancelled = false

    const sync = async () => {
      try {
        const token = await getToken()
        if (!cancelled && token) {
          setAuthToken(token)
          setTokenReady(true)
        }
      } catch {
        // Token sync failed — Clerk will still try
      }
    }

    sync()

    // Allow client.js to auto-refresh the token when API calls get 401
    setTokenRefresh(async () => {
      const freshToken = await getToken()
      return freshToken || null
    })

    // Re-sync every 30 seconds to keep the token fresh
    const interval = setInterval(sync, 30 * 1000)

    return () => {
      cancelled = true
      clearInterval(interval)
    }
  }, [isLoaded, isSignedIn, getToken])

  if (!isLoaded) {
    return (
      <div className="loading-screen">
        <span className="loading-spinner" />
      </div>
    )
  }

  if (!tokenReady) {
    return (
      <div className="loading-screen">
        <span className="loading-spinner" />
        <p style={{ color: '#6b7280', marginTop: 16, fontSize: '0.9rem' }}>
          Signing in...
        </p>
      </div>
    )
  }

  return (
    <>
      <SignedIn>
        <AppContent />
      </SignedIn>
      <SignedOut>
        <SignInPage />
      </SignedOut>
    </>
  )
}

export default App
