import React, { useState, useEffect, useRef, useCallback, useLayoutEffect } from 'react'
import ReactMarkdown from 'react-markdown'
import remarkMath from 'remark-math'
import remarkGfm from 'remark-gfm'
import rehypeKatex from 'rehype-katex'
import { Copy, Check, ChevronDown, ChevronUp, Bot, User, FileText, FileDown, FileCode, Download } from 'lucide-react'
import { jsPDF } from 'jspdf'
import html2canvas from 'html2canvas'
import { preprocessLaTeX, parseMessageContent } from '../utils/chatUtils'

import ErrorBoundary from './ErrorBoundary'
import calculusIcon from '../assets/calculus-icon.png'

const MessageFooter = ({ role, onCopy, onToggleExpand, isExpanded, isOverflow, copiedId, idx, onExportMD, onExportPDF, onExportLaTeX }) => {
    const [showMenu, setShowMenu] = useState(false)

    return (
        <div className="message-footer">
            {isOverflow && (
                <button className="footer-btn expand-toggle" onClick={onToggleExpand} title={isExpanded ? "Thu gọn" : "Xem thêm"}>
                    {isExpanded ? <ChevronUp size={16} /> : <ChevronDown size={16} />}
                </button>
            )}
            <div className="footer-actions-right">
                <button
                    onClick={onCopy}
                    title="Sao chép"
                    className={`footer-btn copy-btn ${copiedId === idx ? 'copied' : ''}`}
                >
                    {copiedId === idx ? <Check size={16} /> : <Copy size={16} />}
                    {copiedId === idx && <span className="copy-toast">Đã copy</span>}
                </button>

                {role === 'assistant' && (
                    <div className="export-dropdown-wrapper">
                        <button
                            className="footer-btn export-trigger"
                            onClick={() => setShowMenu(!showMenu)}
                            title="Tải về"
                        >
                            <Download size={16} />
                        </button>
                        {showMenu && (
                            <div className="export-menu" onMouseLeave={() => setShowMenu(false)}>
                                <button onClick={() => { onExportMD(); setShowMenu(false); }}>
                                    <FileText size={14} /> <span>Markdown (.md)</span>
                                </button>
                                <button onClick={() => { onExportLaTeX(); setShowMenu(false); }}>
                                    <FileCode size={14} /> <span>LaTeX (.tex)</span>
                                </button>
                                <button onClick={() => { onExportPDF(); setShowMenu(false); }}>
                                    <FileDown size={14} /> <span>PDF (.pdf)</span>
                                </button>
                            </div>
                        )}
                    </div>
                )}
            </div>
        </div>
    )
}

const CollapsibleContent = ({ content, messageId, maxLines = 12, isStreaming = false, children }) => {
    const [expanded, setExpanded] = useState(() => {
        if (!messageId) return false
        return localStorage.getItem(messageId) === 'true'
    })
    // Maintain expanded state after streaming finishes for the current session
    const [wasStreaming, setWasStreaming] = useState(false)

    useEffect(() => {
        if (isStreaming && !wasStreaming) {
            setWasStreaming(true)
            setExpanded(true)
        }
    }, [isStreaming, wasStreaming])

    const [isOverflow, setIsOverflow] = useState(false)
    const contentRef = useRef(null)

    useEffect(() => {
        if (contentRef.current) {
            const lineHeight = parseFloat(getComputedStyle(contentRef.current).lineHeight)
            const maxHeight = lineHeight * maxLines
            setIsOverflow(contentRef.current.scrollHeight > maxHeight + 10)
        }
    }, [content, maxLines])

    const toggleExpand = () => {
        const nextState = !expanded
        setExpanded(nextState)
        if (messageId) {
            localStorage.setItem(messageId, String(nextState))
        }
    }

    return (
        <div className={`collapsible-content ${expanded ? 'expanded' : ''} ${isOverflow && !expanded ? 'truncated' : ''}`}>
            <div
                ref={contentRef}
                className="content-inner message-content"
                style={(!expanded && isOverflow && !isStreaming) ? { maxHeight: `${maxLines * 1.7}em`, overflow: 'hidden' } : {}}
            >
                <ErrorBoundary>
                    <ReactMarkdown
                        remarkPlugins={[remarkMath, remarkGfm]}
                        rehypePlugins={[[rehypeKatex, { strict: false, trust: true, throwOnError: false }]]}
                        components={{
                            a: ({ node, ...props }) => <a {...props} target="_blank" rel="noopener noreferrer" />
                        }}
                    >
                        {preprocessLaTeX(parseMessageContent(content))}
                    </ReactMarkdown>
                </ErrorBoundary>
            </div>
            {children({ isOverflow, isExpanded: expanded, onToggleExpand: toggleExpand })}
        </div>
    )
}

const MessageList = ({
    messages,
    isLoading,
    conversationId,
    onExampleClick,
    onImageClick,
    userAvatar,
    userName = 'User'
}) => {
    const messagesEndRef = useRef(null)
    const containerRef = useRef(null)
    const [showScrollBtn, setShowScrollBtn] = useState(false)
    const [isRestored, setIsRestored] = useState(false)
    const [isTransitioning, setIsTransitioning] = useState(false)
    const scrollPositionsRef = useRef({}) // Persistent in-memory scroll storage

    const prevConversationId = useRef(conversationId)
    const prevMessagesLengthRef = useRef(0)
    const prevStreamingRef = useRef(false)
    const [copiedId, setCopiedId] = useState(null)
    const pdfExportRef = useRef(null)
    const [exportingIndex, setExportingIndex] = useState(null)

    const scrollToBottom = (behavior = 'smooth') => {
        if (containerRef.current) {
            const container = containerRef.current
            if (behavior === 'smooth') {
                // Use requestAnimationFrame to ensure React has rendered the new content
                requestAnimationFrame(() => {
                    container.scrollTo({
                        top: container.scrollHeight,
                        behavior: 'smooth'
                    })
                })
            } else {
                container.scrollTop = container.scrollHeight
            }
        }
    }

    const handleScroll = useCallback(() => {
        if (containerRef.current && conversationId && isRestored && !isTransitioning) {
            const { scrollTop, scrollHeight, clientHeight } = containerRef.current
            // Save to both Ref (instant access) and SessionStorage (persistence)
            scrollPositionsRef.current[conversationId] = scrollTop
            sessionStorage.setItem(`scroll_${conversationId}`, String(scrollTop))
            setShowScrollBtn(scrollHeight - scrollTop - clientHeight > 100)
        }
    }, [conversationId, isRestored, isTransitioning])

    // Detect Session Change
    useLayoutEffect(() => {
        if (prevConversationId.current !== conversationId) {
            // Store current position before switching
            if (containerRef.current && prevConversationId.current) {
                scrollPositionsRef.current[prevConversationId.current] = containerRef.current.scrollTop
            }

            setIsRestored(false)
            // Only set transitioning if we're moving from one real session to another
            // This prevents "white screen" on new sessions while streaming starts
            setIsTransitioning(!!prevConversationId.current && !!conversationId)
            prevConversationId.current = conversationId
            prevMessagesLengthRef.current = 0
        }
    }, [conversationId])

    // Restore Scroll Position
    useLayoutEffect(() => {
        if (!containerRef.current || messages.length === 0 || !conversationId) {
            if (messages.length === 0 && conversationId) {
                setIsTransitioning(false) // No messages, nothing to restore
                setIsRestored(true)
            }
            return
        }
        if (isRestored) return

        const container = containerRef.current

        // Priority: Ref -> SessionStorage -> Bottom
        const savedScroll = scrollPositionsRef.current[conversationId] ??
            sessionStorage.getItem(`scroll_${conversationId}`)

        // Use 'auto' behavior for instant restoration (no jump)
        if (savedScroll !== null) {
            container.scrollTo({
                top: parseInt(savedScroll, 10),
                behavior: 'auto'
            })
        } else {
            container.scrollTo({
                top: container.scrollHeight,
                behavior: 'auto'
            })
        }

        // Force a layout reflow to ensure scroll is applied before showing
        void container.offsetHeight

        // If it's a session switch (isTransitioning), we use a small delay to hide the "jump"
        if (isTransitioning) {
            const timer = setTimeout(() => {
                setIsRestored(true)
                setIsTransitioning(false)
                prevMessagesLengthRef.current = messages.length
            }, 50)
            return () => clearTimeout(timer)
        } else {
            // --- REFRESH CASE (INITIAL LOAD) ---
            // Set isRestored to true to start animations
            // Set prevMessagesLength to 0 to make ALL messages animate from the start
            setIsRestored(true)
            prevMessagesLengthRef.current = 0
        }
    }, [messages.length, conversationId, isRestored, isTransitioning])

    const isInitialLoadRef = useRef(true)

    // Handle New Messages
    useEffect(() => {
        if (!isRestored || isTransitioning || messages.length === 0) return

        const isNewMessage = messages.length > prevMessagesLengthRef.current

        // If it's the initial load (refresh), we want animations but NOT auto-scroll
        if (isInitialLoadRef.current) {
            isInitialLoadRef.current = false
            prevMessagesLengthRef.current = messages.length
            return
        }

        const lastMessage = messages[messages.length - 1]
        const isUserMessage = lastMessage?.role === 'user'

        if (isNewMessage) {
            // Always scroll to bottom for user messages
            // For bot messages, only scroll if already at bottom (sticky)
            if (isUserMessage || !showScrollBtn) {
                scrollToBottom('smooth')
            }
        }

        prevMessagesLengthRef.current = messages.length
    }, [messages.length, showScrollBtn, isRestored, isTransitioning])

    // Auto-scroll during streaming to keep user's view locked on new content
    const lastMessageContent = messages[messages.length - 1]?.content
    const isLastMessageStreaming = messages[messages.length - 1]?.isStreaming

    useEffect(() => {
        if (!containerRef.current) return

        if (isLastMessageStreaming) {
            // "Sticky Scroll": Only auto-scroll if user is already near the bottom
            // !showScrollBtn means distance to bottom < 100px
            if (!showScrollBtn) {
                containerRef.current.scrollTop = containerRef.current.scrollHeight
            }
        } else if (prevStreamingRef.current) {
            // Just finished streaming - do one final sync to be sure
            // but only if the user didn't scroll too far up
            if (!showScrollBtn) {
                scrollToBottom('smooth')
            }
        }

        prevStreamingRef.current = isLastMessageStreaming
    }, [lastMessageContent, isLastMessageStreaming, showScrollBtn])

    const copyToClipboard = (text, idx) => {
        navigator.clipboard.writeText(text)
        setCopiedId(idx)
        setTimeout(() => setCopiedId(null), 2000)
    }

    const exportToMarkdown = (content, idx) => {
        const blob = new Blob([content], { type: 'text/markdown' })
        const url = URL.createObjectURL(blob)
        const a = document.createElement('a')
        a.href = url
        a.download = `chat-answer-${idx + 1}.md`
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
        URL.revokeObjectURL(url)
    }

    const exportToLaTeX = (content, idx) => {
        const texContent = `\\documentclass{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage{amsmath}\n\n\\begin{document}\n${content}\n\\end{document}`
        const blob = new Blob([texContent], { type: 'text/x-tex' })
        const url = URL.createObjectURL(blob)
        const a = document.createElement('a')
        a.href = url
        a.download = `chat-answer-${idx + 1}.tex`
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
        URL.revokeObjectURL(url)
    }

    const exportToPDF = async (idx) => {
        setExportingIndex(idx)

        // Wait for DOM to update the hidden element
        setTimeout(async () => {
            if (!pdfExportRef.current) return

            try {
                const canvas = await html2canvas(pdfExportRef.current, {
                    scale: 3,
                    useCORS: true,
                    backgroundColor: '#ffffff',
                    logging: false,
                })

                const imgData = canvas.toDataURL('image/png')
                const pdfWidth = 595.28
                const pdfHeight = 841.89
                const pdf = new jsPDF('p', 'pt', 'a4')

                const margin = 0 // Container already has padding
                const innerWidth = pdfWidth
                const imgProps = pdf.getImageProperties(imgData)
                const imgHeight = (imgProps.height * innerWidth) / imgProps.width

                let heightLeft = imgHeight
                let position = 0

                pdf.addImage(imgData, 'PNG', 0, position, innerWidth, imgHeight)
                heightLeft -= pdfHeight

                while (heightLeft >= 0) {
                    pdf.addPage()
                    position = heightLeft - imgHeight
                    pdf.addImage(imgData, 'PNG', 0, position, innerWidth, imgHeight)
                    heightLeft -= pdfHeight
                }

                pdf.save(`chat-answer-${idx + 1}.pdf`)
                setExportingIndex(null)
            } catch (error) {
                console.error('PDF Export failed:', error)
                setExportingIndex(null)
            }
        }, 100)
    }

    if (messages.length === 0) {
        return (
            <div className="welcome-screen">
                <div id="tour-chat-interface" className="tour-chat-spotlight"></div>
                <div className="welcome-icon">
                    <img src={calculusIcon} alt="Icon" onError={(e) => e.target.style.display = 'none'} />
                    <div className="p-4 bg-indigo-100 rounded-full dark:bg-indigo-900/30" style={{ display: 'none' }}>
                        <Bot size={48} className="text-indigo-600 dark:text-indigo-400" />
                    </div>
                </div>
                <h2>Xin chào, tôi có thể giúp gì?</h2>
                <p>Tôi là Pochi, bạn đồng hành của bạn trong việc chinh phục môn toán giải tích.<br />Hãy bắt đầu bằng việc đặt câu hỏi cho tôi nhé!</p>
                <div className="example-prompts">
                    <button onClick={() => onExampleClick('Tính đạo hàm của hàm số y = x³ - 3x + 2')}>Tính đạo hàm của hàm số y = x³ - 3x + 2</button>
                    <button onClick={() => onExampleClick('Tính tích phân của hàm số f(x) = sin(x) từ 0 đến π')}>Tính tích phân của hàm số f(x) = sin(x) từ 0 đến π</button>
                    <button onClick={() => onExampleClick('Tìm cực trị của hàm số y = x⁴ - 2x²')}>Tìm cực trị của hàm số y = x⁴ - 2x²</button>
                </div>
            </div>
        )
    }

    return (
        <div className="messages-section">
            <div id="tour-chat-interface" className="tour-chat-spotlight"></div>
            <div
                className={`messages-container ${isTransitioning ? 'transitioning' : ''}`}
                ref={containerRef}
                onScroll={handleScroll}
            >
                {messages.map((msg, idx) => (
                    <div
                        key={`${idx}-${msg.role}`}
                        className={`message ${msg.role} ${msg.isStreaming ? 'streaming' : ''} ${isRestored && idx >= prevMessagesLengthRef.current - 1 ? 'animate-msg-slide-up' : ''}`}
                        style={{ animationDelay: isRestored ? `${Math.min((idx - (prevMessagesLengthRef.current - 1)) * 0.05, 0.5)}s` : '0s' }}
                    >
                        {/* Avatar removed */}

                        <div className="message-body">
                            {msg.status && <div className="agent-status-badge">{msg.status}</div>}
                            {msg.images && msg.images.length > 0 && (
                                <div className="message-images-list">
                                    {msg.images.map((src, i) => (
                                        <div key={i} className="message-image-preview" onClick={() => onImageClick(msg.images, i)}>
                                            <img src={src} alt={`Attachment ${i}`} />
                                        </div>
                                    ))}
                                </div>
                            )}

                            {msg.content ? (
                                <CollapsibleContent
                                    content={msg.content}
                                    messageId={conversationId ? `expand_${conversationId}_${idx}` : null}
                                    isStreaming={msg.isStreaming}
                                >
                                    {({ isOverflow, isExpanded, onToggleExpand }) => (
                                        <MessageFooter
                                            role={msg.role}
                                            isOverflow={isOverflow}
                                            isExpanded={isExpanded}
                                            onToggleExpand={onToggleExpand}
                                            onCopy={() => copyToClipboard(msg.content, idx)}
                                            onExportMD={() => exportToMarkdown(msg.content, idx)}
                                            onExportPDF={() => exportToPDF(idx)}
                                            onExportLaTeX={() => exportToLaTeX(msg.content, idx)}
                                            copiedId={copiedId}
                                            idx={idx}
                                        />
                                    )}
                                </CollapsibleContent>
                            ) : msg.role === 'assistant' ? (
                                <div className="thinking-indicator"><span></span><span></span><span></span>Đang suy nghĩ...</div>
                            ) : (
                                <span className="text-gray-400 italic">...</span>
                            )}
                        </div>
                    </div>
                ))}
                <div ref={messagesEndRef} />
            </div>

            {/* Hidden Premium PDF Layout Component */}
            {exportingIndex !== null && (
                <div className="pdf-export-container" ref={pdfExportRef}>
                    {/* Background Watermark */}
                    <div className="pdf-watermark">POCHI</div>

                    <div className="pdf-header">
                        <div className="pdf-brand">POCHI</div>
                        <div className="pdf-meta">
                            <div>Assistant Export</div>
                            <div>{new Date().toLocaleDateString('vi-VN')}</div>
                        </div>
                    </div>
                    <div className="pdf-content">
                        <ReactMarkdown
                            remarkPlugins={[remarkMath, remarkGfm]}
                            rehypePlugins={[[rehypeKatex, { strict: false, trust: true, throwOnError: false }]]}
                        >
                            {preprocessLaTeX(parseMessageContent(messages[exportingIndex].content))}
                        </ReactMarkdown>
                    </div>
                    <div className="pdf-footer">
                        Tài liệu được tạo bởi Pochi
                    </div>
                </div>
            )}

            {showScrollBtn && (
                <button className="scroll-to-bottom" onClick={() => scrollToBottom('smooth')}>
                    <ChevronDown size={20} />
                </button>
            )}
        </div>
    )
}

export default MessageList
