import { useEffect, useRef, useState } from 'react'
import api from '../api/client'

const TAB_POSITION_KEY = 'pedshub_mynote_tab_position'

function formatSavedAt(value) {
  if (!value) return 'Not saved yet'
  return `Saved ${new Date(value).toLocaleString()}`
}

function clampPosition(x, y, width, height) {
  const margin = 8
  return {
    x: Math.min(Math.max(margin, x), Math.max(margin, window.innerWidth - width - margin)),
    y: Math.min(Math.max(margin, y), Math.max(margin, window.innerHeight - height - margin)),
  }
}

export default function MyNote({ variant = 'tab' }) {
  const [open, setOpen] = useState(false)
  const [content, setContent] = useState('')
  const [updatedAt, setUpdatedAt] = useState(null)
  const [loading, setLoading] = useState(false)
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState('')
  const [position, setPosition] = useState(null)
  const [dragging, setDragging] = useState(false)
  const tabRef = useRef(null)
  const saveRef = useRef(null)
  const loadedRef = useRef(false)
  const dragRef = useRef(null)
  const draggedRef = useRef(false)
  const textareaRef = useRef(null)

  const loadNote = async () => {
    if (loadedRef.current) return
    setLoading(true)
    setError('')
    try {
      const res = await api.get('/mynote')
      setContent(res.data.content || '')
      setUpdatedAt(res.data.updated_at || null)
      loadedRef.current = true
    } catch {
      setError('Could not load MyNote')
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    if (variant === 'card') loadNote()
  }, [variant])

  useEffect(() => {
    if (variant !== 'tab') return
    const rect = tabRef.current?.getBoundingClientRect()
    let next = null
    try {
      const saved = JSON.parse(localStorage.getItem(TAB_POSITION_KEY) || 'null')
      if (saved && Number.isFinite(saved.x) && Number.isFinite(saved.y)) {
        next = clampPosition(saved.x, saved.y, rect?.width || 120, rect?.height || 48)
      }
    } catch {
      next = null
    }
    if (!next && rect) next = { x: rect.left, y: rect.top }
    if (next) setPosition(next)

    const handleResize = () => {
      setPosition(current => {
        if (!current) return current
        const resizedRect = tabRef.current?.getBoundingClientRect()
        const clamped = clampPosition(current.x, current.y, resizedRect?.width || 120, resizedRect?.height || 48)
        localStorage.setItem(TAB_POSITION_KEY, JSON.stringify(clamped))
        return clamped
      })
    }
    window.addEventListener('resize', handleResize)
    return () => window.removeEventListener('resize', handleResize)
  }, [variant])

  useEffect(() => {
    if (variant !== 'tab') return
    setPosition(current => {
      if (!current) return current
      const rect = tabRef.current?.getBoundingClientRect()
      if (!rect) return current
      return clampPosition(current.x, current.y, rect.width, rect.height)
    })
  }, [open, variant])

  useEffect(() => {
    if (!loadedRef.current) return
    clearTimeout(saveRef.current)
    saveRef.current = setTimeout(async () => {
      setSaving(true)
      setError('')
      try {
        const res = await api.put('/mynote', { content })
        setUpdatedAt(res.data.updated_at || null)
      } catch {
        setError('Could not save MyNote')
      } finally {
        setSaving(false)
      }
    }, 700)
    return () => clearTimeout(saveRef.current)
  }, [content])

  useEffect(() => {
    if (!open || loading) return
    requestAnimationFrame(() => {
      const textarea = textareaRef.current
      if (!textarea) return
      const end = textarea.value.length
      textarea.focus()
      textarea.setSelectionRange(end, end)
      textarea.scrollTop = textarea.scrollHeight
    })
  }, [open, loading])

  const openNote = () => {
    setOpen(true)
    loadNote()
  }

  const startDrag = event => {
    if (variant !== 'tab' || event.button !== 0) return
    if (event.target.closest('button, textarea') && event.currentTarget !== event.target) return
    const rect = tabRef.current?.getBoundingClientRect()
    if (!rect) return
    dragRef.current = {
      pointerId: event.pointerId,
      offsetX: event.clientX - rect.left,
      offsetY: event.clientY - rect.top,
      startX: event.clientX,
      startY: event.clientY,
      moved: false,
      position: { x: rect.left, y: rect.top },
    }
    event.currentTarget.setPointerCapture?.(event.pointerId)
  }

  const moveDrag = event => {
    const drag = dragRef.current
    if (!drag || drag.pointerId !== event.pointerId) return
    const rect = tabRef.current?.getBoundingClientRect()
    if (!rect) return
    const next = clampPosition(event.clientX - drag.offsetX, event.clientY - drag.offsetY, rect.width, rect.height)
    drag.position = next
    if (Math.abs(event.clientX - drag.startX) > 4 || Math.abs(event.clientY - drag.startY) > 4) {
      drag.moved = true
      setDragging(true)
    }
    setPosition(next)
    event.preventDefault()
  }

  const stopDrag = event => {
    const drag = dragRef.current
    if (!drag || drag.pointerId !== event.pointerId) return
    if (drag.moved) {
      localStorage.setItem(TAB_POSITION_KEY, JSON.stringify(drag.position))
    }
    draggedRef.current = drag.moved
    dragRef.current = null
    setDragging(false)
    setTimeout(() => {
      draggedRef.current = false
    }, 0)
  }

  const openFromTabButton = event => {
    if (draggedRef.current) {
      event.preventDefault()
      return
    }
    openNote()
  }

  const preview = content.trim()
    ? content.trim().slice(0, 150) + (content.trim().length > 150 ? '...' : '')
    : 'Your single study note will appear here once you start writing during quizzes.'

  const editor = (
    <div className="mynote-editor">
      <div
        className={`mynote-editor-header ${variant === 'tab' ? 'mynote-drag-handle' : ''}`}
        onPointerDown={variant === 'tab' ? startDrag : undefined}
      >
        <div>
          <div className="mynote-title">MyNote</div>
          <div className="mynote-status">{variant === 'tab' ? 'Drag this header to move. ' : ''}{saving ? 'Saving...' : formatSavedAt(updatedAt)}</div>
        </div>
        {variant === 'tab' && <button className="mynote-close" type="button" onClick={() => setOpen(false)}>Collapse</button>}
      </div>
      {error && <div className="mynote-error">{error}</div>}
      <textarea
        ref={textareaRef}
        value={content}
        onChange={e => setContent(e.target.value)}
        placeholder={loading ? 'Loading MyNote...' : 'Capture one running note across all quizzes...'}
        disabled={loading}
      />
    </div>
  )

  if (variant === 'card') {
    return (
      <div className="card mynote-card">
        <div className="mynote-card-copy">
          <div className="mynote-eyebrow">Saved across all quiz sessions</div>
          <h2>MyNote</h2>
          <p>{preview}</p>
          <span>{formatSavedAt(updatedAt)}</span>
        </div>
        <button className="btn btn-primary" type="button" onClick={openNote}>Open MyNote</button>
        {open && (
          <div className="mynote-modal" role="dialog" aria-modal="true" aria-label="MyNote" onClick={() => setOpen(false)}>
            <div className="mynote-modal-panel" onClick={e => e.stopPropagation()}>
              <button className="mynote-modal-close" type="button" onClick={() => setOpen(false)} aria-label="Close MyNote">×</button>
              {editor}
            </div>
          </div>
        )}
      </div>
    )
  }

  return (
    <div
      ref={tabRef}
      className={`mynote-tab ${open ? 'open' : ''} ${dragging ? 'dragging' : ''}`}
      style={position ? { left: position.x, top: position.y, right: 'auto', bottom: 'auto' } : undefined}
      onPointerMove={moveDrag}
      onPointerUp={stopDrag}
      onPointerCancel={stopDrag}
    >
      {!open ? (
        <button className="mynote-tab-button" type="button" onPointerDown={startDrag} onClick={openFromTabButton}>MyNote</button>
      ) : editor}
    </div>
  )
}
