import { useState, useEffect, useRef } from 'react'
import { marked } from 'marked'
import DOMPurify from 'dompurify'
import { useEditorStore } from '../../store/editorStore'
import type { TextAnnotation } from '../../types/editor'
import {
  tooltipAnalysisCache,
  cancelPendingDismiss,
  analyseAnnotation,
  scrollToAnnotation,
  applyAnnotation
} from '../Editor/MarkdownEditor'
import './FeedbackPanel.css'

type AnalysisState =
  | { status: 'idle' }
  | { status: 'streaming'; text: string }
  | { status: 'done'; text: string; suggestion: string | null }

function badgeColor(type: TextAnnotation['type']): string {
  switch (type) {
    case 'passive_voice':  return 'rgba(255, 200, 0, 0.75)'
    case 'consistency':    return 'rgba(220, 80, 80, 0.75)'
    case 'style':          return 'rgba(80, 160, 255, 0.75)'
    case 'show_tell':      return 'rgba(255, 140, 30, 0.75)'
    case 'critique':       return 'rgba(160, 80, 220, 0.75)'
    case 'custom':         return 'rgba(30, 200, 150, 0.8)'
    case 'user_comment':   return 'rgba(240, 100, 180, 0.85)'
    case 'document_note':  return 'rgba(80, 180, 240, 0.85)'
  }
}

function renderMarkdown(text: string, streaming: boolean): string {
  const raw = marked.parse(streaming ? text + ' ▋' : text) as string
  return DOMPurify.sanitize(raw)
}

interface FeedbackCardProps {
  ann: TextAnnotation
  autoAnalyse: boolean
  onDismiss: () => void
}

function FeedbackCard({ ann, autoAnalyse, onDismiss }: FeedbackCardProps): JSX.Element {
  const [state, setState] = useState<AnalysisState>(() => {
    const cached = tooltipAnalysisCache.get(ann.id) ?? ann.analysisCache ?? null
    if (cached) return { status: 'done', text: cached.text, suggestion: cached.suggestion }
    // Custom (attachment-driven) annotations already carry their analysis — show
    // the problem description and suggestion immediately without an extra AI call.
    // Context-menu annotations (autoAnalyse: true) need AI analysis, so start idle.
    if (ann.type === 'custom' && !ann.autoAnalyse) {
      return { status: 'done', text: ann.message, suggestion: ann.suggestion ?? null }
    }
    return { status: 'idle' }
  })

  const cleanupRef = useRef<(() => void) | null>(null)

  function startAnalysis(): void {
    // Prevent double-start
    if (state.status === 'streaming') return
    cleanupRef.current?.()
    setState({ status: 'streaming', text: '' })
    cleanupRef.current = analyseAnnotation(ann, (text, streaming, suggestion) => {
      if (streaming) {
        setState({ status: 'streaming', text })
      } else {
        setState({ status: 'done', text, suggestion })
      }
    })
  }

  // Trigger analysis when parent requests "Analyse all"
  useEffect(() => {
    if (autoAnalyse && state.status === 'idle') {
      startAnalysis()
    }
  }, [autoAnalyse]) // eslint-disable-line react-hooks/exhaustive-deps

  // Cleanup on unmount
  useEffect(() => {
    return () => { cleanupRef.current?.() }
  }, [])

  // When a hover tooltip completes analysis for this annotation, hydrate the card
  // from the cache so the sidebar reflects the result without requiring a manual click.
  useEffect(() => {
    const handler = (e: Event): void => {
      const { id } = (e as CustomEvent<{ id: string }>).detail
      if (id !== ann.id) return
      const cached = tooltipAnalysisCache.get(ann.id)
      if (!cached) return
      setState(prev =>
        prev.status === 'idle'
          ? { status: 'done', text: cached.text, suggestion: cached.suggestion }
          : prev
      )
    }
    window.addEventListener('annotation-cached', handler)
    return () => window.removeEventListener('annotation-cached', handler)
  }, [ann.id])

  const typeName = ann.type.replace(/_/g, ' ')
  const isSpinning = state.status === 'streaming' && state.text === ''
  const hasText = (state.status === 'streaming' || state.status === 'done') && state.text !== ''
  const suggestion = state.status === 'done' ? state.suggestion : null

  return (
    <div
      className={`fb-card fb-card-${ann.type}`}
      style={{ '--badge-color': badgeColor(ann.type) } as React.CSSProperties}
    >
      {/* Header — click to jump to passage in editor */}
      <div className="fb-card-header" onClick={() => scrollToAnnotation(ann)} title="Jump to passage">
        <div className="fb-card-header-top">
          <div className="fb-card-header-badges">
            <span className="fb-card-badge">{typeName}</span>
            {ann.type === 'custom' && !ann.autoAnalyse && (
              <span className="fb-card-source-tag">from attachment</span>
            )}
          </div>
          <button
            className="fb-card-dismiss"
            onClick={(e) => { e.stopPropagation(); onDismiss() }}
            title="Dismiss"
          >
            ×
          </button>
        </div>
        <span className="fb-card-excerpt">"{ann.matchedText}"</span>
      </div>

      {/* Idle: show Analyse button */}
      {state.status === 'idle' && (
        <button className="fb-card-analyse-btn" onClick={startAnalysis}>
          Analyse
        </button>
      )}

      {/* Streaming with no text yet: show bouncing dots */}
      {isSpinning && (
        <div className="fb-card-loading">
          <span /><span /><span />
        </div>
      )}

      {/* Streaming or done with text: show markdown body */}
      {hasText && (
        <div
          className="fb-card-analysis chat-message-markdown"
          dangerouslySetInnerHTML={{
            __html: renderMarkdown(state.text, state.status === 'streaming')
          }}
        />
      )}

      {/* Done with a suggestion: show Apply button */}
      {suggestion != null && (
        <button
          className="fb-card-apply"
          onClick={() => applyAnnotation(ann, suggestion)}
        >
          Apply suggestion
        </button>
      )}
    </div>
  )
}

interface UserCommentCardProps {
  ann: TextAnnotation
  onDismiss: () => void
}

function UserCommentCard({ ann, onDismiss }: UserCommentCardProps): JSX.Element {
  return (
    <div
      className="fb-card fb-card-user_comment"
      style={{ '--badge-color': 'rgba(240, 100, 180, 0.85)' } as React.CSSProperties}
    >
      <div className="fb-card-header" onClick={() => scrollToAnnotation(ann)} title="Jump to passage">
        <div className="fb-card-header-top">
          <div className="fb-card-header-badges">
            <span className="fb-card-badge">Your comment</span>
          </div>
          <button
            className="fb-card-dismiss"
            onClick={(e) => { e.stopPropagation(); onDismiss() }}
            title="Dismiss"
          >
            ×
          </button>
        </div>
        <span className="fb-card-excerpt">"{ann.matchedText}"</span>
      </div>
      <div className="fb-card-user-comment-body">{ann.comment}</div>
    </div>
  )
}

interface DocumentNoteCardProps {
  ann: TextAnnotation
  onDismiss: () => void
}

function DocumentNoteCard({ ann, onDismiss }: DocumentNoteCardProps): JSX.Element {
  return (
    <div
      className="fb-card fb-card-document_note"
      style={{ '--badge-color': 'rgba(80, 180, 240, 0.85)' } as React.CSSProperties}
    >
      <div className="fb-card-header fb-card-header--no-jump">
        <div className="fb-card-header-top">
          <div className="fb-card-header-badges">
            <span className="fb-card-badge">Document note</span>
          </div>
          <button
            className="fb-card-dismiss"
            onClick={onDismiss}
            title="Dismiss"
          >
            ×
          </button>
        </div>
      </div>
      <div className="fb-card-user-comment-body">{ann.comment}</div>
    </div>
  )
}

interface ArchiveCardProps {
  ann: TextAnnotation
  onRemove?: () => void
}

function ArchiveCard({ ann, onRemove }: ArchiveCardProps): JSX.Element {
  const typeName = ann.type.replace(/_/g, ' ')
  const status = ann.applied ? 'applied' : 'dismissed'

  return (
    <div
      className={`fb-archive-card fb-archive-card--${status}`}
      style={{ '--badge-color': badgeColor(ann.type) } as React.CSSProperties}
    >
      <div className="fb-archive-card-header">
        <div className="fb-archive-card-badges">
          <span className="fb-card-badge">{typeName}</span>
          <span className={`fb-archive-status fb-archive-status--${status}`}>{status}</span>
        </div>
        {onRemove && (
          <button className="fb-archive-card-dismiss" onClick={onRemove} title="Remove from archive">
            ×
          </button>
        )}
      </div>
      {ann.matchedText && (
        <span className="fb-archive-card-excerpt">"{ann.matchedText}"</span>
      )}
      {ann.comment && (
        <span className="fb-archive-card-comment">{ann.comment}</span>
      )}
      {ann.suggestion && (
        <span className="fb-archive-card-suggestion">→ {ann.suggestion}</span>
      )}
    </div>
  )
}

export function FeedbackPanel(): JSX.Element {
  const {
    annotations,
    annotationsByFile,
    activeFilePath,
    clearAnnotations,
    removeAnnotation,
    clearArchivedAnnotations,
    removeArchivedAnnotation,
    addDocumentNote,
  } = useEditorStore()
  const [analyseAll, setAnalyseAll] = useState(false)
  const [addingNote, setAddingNote] = useState(false)
  const [noteText, setNoteText] = useState('')
  const noteTextareaRef = useRef<HTMLTextAreaElement>(null)

  useEffect(() => {
    if (addingNote) noteTextareaRef.current?.focus()
  }, [addingNote])

  function handleSaveNote(): void {
    const trimmed = noteText.trim()
    if (trimmed) addDocumentNote(trimmed)
    setNoteText('')
    setAddingNote(false)
  }

  function handleNoteKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>): void {
    if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
      e.preventDefault()
      handleSaveNote()
    }
    if (e.key === 'Escape') {
      setNoteText('')
      setAddingNote(false)
    }
  }

  const archivedAnnotations = activeFilePath
    ? (annotationsByFile[activeFilePath]?.annotations ?? []).filter(a => a.applied || a.dismissed)
    : []
  const dismissedCount = archivedAnnotations.filter(a => a.dismissed).length

  // Reset "Analyse all" whenever the annotation set changes (new critique run),
  // so auto-analysis doesn't carry over to fresh results unexpectedly.
  const prevAnnotationsRef = useRef(annotations)
  useEffect(() => {
    if (prevAnnotationsRef.current !== annotations) {
      setAnalyseAll(false)
      prevAnnotationsRef.current = annotations
    }
  }, [annotations])

  function handleClearAll(): void {
    clearAnnotations()
    tooltipAnalysisCache.clear()
  }

  const hasActive = annotations.length > 0
  const hasArchive = archivedAnnotations.length > 0

  if (!hasActive && !hasArchive) {
    return (
      <div className="fb-panel">
        <div className="fb-empty">
          <p>No feedback yet.</p>
          <p>Run a critique from the toolbar to highlight issues in your text.</p>
        </div>
        <div className="fb-add-note-section">
          {addingNote ? (
            <div className="fb-note-form">
              <textarea
                ref={noteTextareaRef}
                className="fb-note-textarea"
                placeholder="Write a note about this document…"
                value={noteText}
                onChange={(e) => setNoteText(e.target.value)}
                onKeyDown={handleNoteKeyDown}
                rows={3}
              />
              <div className="fb-note-form-actions">
                <button className="fb-note-save-btn" onClick={handleSaveNote}>Save</button>
                <button className="fb-note-cancel-btn" onClick={() => { setNoteText(''); setAddingNote(false) }}>Cancel</button>
              </div>
            </div>
          ) : (
            <button className="fb-add-note-btn" onClick={() => setAddingNote(true)}>
              + Add document note
            </button>
          )}
        </div>
      </div>
    )
  }

  return (
    <div className="fb-panel">
      {hasActive && (
        <>
          <div className="fb-toolbar">
            <button
              className="fb-toolbar-btn"
              onClick={() => setAnalyseAll(true)}
              disabled={analyseAll}
              title="Run AI analysis on all highlighted passages"
            >
              Analyse all
            </button>
            <button
              className="fb-toolbar-btn fb-toolbar-btn--clear"
              onClick={handleClearAll}
              title="Archive all highlights"
            >
              Clear all
            </button>
          </div>

          <div className="fb-list">
            {[...annotations].sort((a, b) => (a.from ?? -1) - (b.from ?? -1)).map(ann => {
              if (ann.type === 'document_note') {
                return (
                  <DocumentNoteCard
                    key={ann.id}
                    ann={ann}
                    onDismiss={() => removeAnnotation(ann.id)}
                  />
                )
              }
              if (ann.type === 'user_comment') {
                return (
                  <UserCommentCard
                    key={ann.id}
                    ann={ann}
                    onDismiss={() => { cancelPendingDismiss(ann.id); removeAnnotation(ann.id) }}
                  />
                )
              }
              return (
                <FeedbackCard
                  key={ann.id}
                  ann={ann}
                  autoAnalyse={analyseAll || ann.autoAnalyse === true}
                  onDismiss={() => { cancelPendingDismiss(ann.id); removeAnnotation(ann.id); tooltipAnalysisCache.delete(ann.id) }}
                />
              )
            })}
          </div>
        </>
      )}

      <div className="fb-add-note-section">
        {addingNote ? (
          <div className="fb-note-form">
            <textarea
              ref={noteTextareaRef}
              className="fb-note-textarea"
              placeholder="Write a note about this document…"
              value={noteText}
              onChange={(e) => setNoteText(e.target.value)}
              onKeyDown={handleNoteKeyDown}
              rows={3}
            />
            <div className="fb-note-form-actions">
              <button className="fb-note-save-btn" onClick={handleSaveNote}>Save</button>
              <button className="fb-note-cancel-btn" onClick={() => { setNoteText(''); setAddingNote(false) }}>Cancel</button>
            </div>
          </div>
        ) : (
          <button className="fb-add-note-btn" onClick={() => setAddingNote(true)}>
            + Add document note
          </button>
        )}
      </div>

      {hasArchive && (
        <details className="fb-archive">
          <summary className="fb-archive-header">
            <span className="fb-archive-title">
              Archive
              <span className="fb-archive-count">{archivedAnnotations.length}</span>
            </span>
            {dismissedCount > 0 && (
              <button
                className="fb-archive-clear-btn"
                onClick={(e) => { e.preventDefault(); clearArchivedAnnotations() }}
                title="Permanently remove all dismissed items"
              >
                Clear dismissed
              </button>
            )}
          </summary>
          <div className="fb-archive-list">
            {archivedAnnotations.map(ann => (
              <ArchiveCard
                key={ann.id}
                ann={ann}
                onRemove={ann.dismissed ? () => removeArchivedAnnotation(ann.id) : undefined}
              />
            ))}
          </div>
        </details>
      )}
    </div>
  )
}
