import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { getBlogPosts } from '../../data/blog';
import {
    getBlogPostsApi,
    createBlogPost,
    updateBlogPost,
    deleteBlogPost,
} from '../../api';
import PullToRefresh from '../../components/PullToRefresh';
import FAB from '../../components/FAB';
import './Blog.css';

// ── 마크다운 렌더러 ──────────────────────────────────────────────────────────

const renderInline = (text) => {
    const normalized = text.replace(/<br\s*\/?>/gi, '\n');
    const pattern =
        /(!\[[^\]]*\]\([^)]+\)|\[[^\]]+\]\([^)]+\)|\*\*[^*]+\*\*|\*[^*]+\*|~~[^~]+~~|`[^`]+`)/g;
    const segments = normalized.split('\n');

    return segments.flatMap((segment, segmentIndex) => {
        const parts = segment.split(pattern).filter(Boolean);
        const rendered = parts.map((part, index) => {
            if (part.startsWith('![')) {
                const match = part.match(/!\[([^\]]*)\]\(([^)]+)\)/);
                if (!match) return <span key={`${part}-${index}`}>{part}</span>;
                const [, alt, src] = match;
                return (
                    <img
                        key={`${part}-${index}`}
                        src={src}
                        alt={alt}
                        className="md-image"
                        loading="lazy"
                    />
                );
            }
            if (part.startsWith('[')) {
                const match = part.match(/\[([^\]]+)\]\(([^)]+)\)/);
                if (!match) return <span key={`${part}-${index}`}>{part}</span>;
                const [, label, href] = match;
                return (
                    <a
                        key={`${part}-${index}`}
                        href={href}
                        target="_blank"
                        rel="noreferrer"
                    >
                        {label}
                    </a>
                );
            }
            if (part.startsWith('**')) {
                return (
                    <strong key={`${part}-${index}`}>{part.replace(/\*\*/g, '')}</strong>
                );
            }
            if (part.startsWith('*')) {
                return <em key={`${part}-${index}`}>{part.replace(/\*/g, '')}</em>;
            }
            if (part.startsWith('~~')) {
                return <del key={`${part}-${index}`}>{part.replace(/~~/g, '')}</del>;
            }
            if (part.startsWith('`')) {
                return <code key={`${part}-${index}`}>{part.replace(/`/g, '')}</code>;
            }
            return <span key={`${part}-${index}`}>{part}</span>;
        });

        if (segmentIndex < segments.length - 1) {
            rendered.push(<br key={`br-${segmentIndex}`} />);
        }

        return rendered;
    });
};

const renderMarkdown = (body) => {
    const lines = body.split(/\r?\n/);
    const blocks = [];
    let list = [];
    let code = [];
    let inCode = false;

    const flushList = () => {
        if (list.length) {
            blocks.push({ type: 'list', items: list });
            list = [];
        }
    };

    const flushCode = () => {
        if (code.length) {
            blocks.push({ type: 'code', value: code.join('\n') });
            code = [];
        }
    };

    lines.forEach((line) => {
        if (line.startsWith('```')) {
            if (inCode) {
                flushCode();
                inCode = false;
            } else {
                flushList();
                inCode = true;
            }
            return;
        }

        if (inCode) {
            code.push(line);
            return;
        }

        if (/^---$/.test(line.trim())) {
            flushList();
            blocks.push({ type: 'hr' });
            return;
        }

        if (/^>\s+/.test(line)) {
            flushList();
            blocks.push({ type: 'quote', value: line.replace(/^>\s+/, '') });
            return;
        }

        if (/^[-*]\s+/.test(line)) {
            list.push(line.replace(/^[-*]\s+/, ''));
            return;
        }

        flushList();

        if (!line.trim()) return;

        if (line.startsWith('###### ')) {
            blocks.push({ type: 'h6', value: line.replace(/^######\s+/, '') });
            return;
        }
        if (line.startsWith('##### ')) {
            blocks.push({ type: 'h5', value: line.replace(/^#####\s+/, '') });
            return;
        }
        if (line.startsWith('#### ')) {
            blocks.push({ type: 'h4', value: line.replace(/^####\s+/, '') });
            return;
        }
        if (line.startsWith('### ')) {
            blocks.push({ type: 'h3', value: line.replace(/^###\s+/, '') });
            return;
        }
        if (line.startsWith('## ')) {
            blocks.push({ type: 'h2', value: line.replace(/^##\s+/, '') });
            return;
        }
        if (line.startsWith('# ')) {
            blocks.push({ type: 'h1', value: line.replace(/^#\s+/, '') });
            return;
        }

        blocks.push({ type: 'p', value: line });
    });

    flushList();
    flushCode();

    return blocks.map((block, index) => {
        if (block.type === 'h1') return <h1 key={index}>{block.value}</h1>;
        if (block.type === 'h2') return <h2 key={index}>{block.value}</h2>;
        if (block.type === 'h3') return <h3 key={index}>{block.value}</h3>;
        if (block.type === 'h4') return <h4 key={index}>{block.value}</h4>;
        if (block.type === 'h5') return <h5 key={index}>{block.value}</h5>;
        if (block.type === 'h6') return <h6 key={index}>{block.value}</h6>;
        if (block.type === 'list')
            return (
                <ul key={index}>
                    {block.items.map((item, itemIndex) => (
                        <li key={itemIndex}>{renderInline(item)}</li>
                    ))}
                </ul>
            );
        if (block.type === 'code')
            return (
                <pre key={index} className="md-code">
                    <code>{block.value}</code>
                </pre>
            );
        if (block.type === 'quote')
            return (
                <blockquote key={index} className="md-quote">
                    {renderInline(block.value)}
                </blockquote>
            );
        if (block.type === 'hr') return <hr key={index} className="md-hr" />;
        return (
            <p key={index} className="md-paragraph">
                {renderInline(block.value)}
            </p>
        );
    });
};

// ── 블로그 에디터 모달 ────────────────────────────────────────────────────────

const PRESET_TAGS = ['일상', '개발', '공부', '아이디어', '기타'];

const BlogEditor = ({ post, onSave, onClose }) => {
    const [title, setTitle] = useState(post?.title || '');
    const [tags, setTags] = useState(post?.tags || []);
    const [body, setBody] = useState(post?.body || '');
    const [showPreview, setShowPreview] = useState(false);
    const [saving, setSaving] = useState(false);
    const textareaRef = useRef(null);

    // Tab 키로 들여쓰기 삽입
    const handleKeyDown = (e) => {
        if (e.key === 'Tab') {
            e.preventDefault();
            const el = textareaRef.current;
            const start = el.selectionStart;
            const end = el.selectionEnd;
            const next = body.substring(0, start) + '  ' + body.substring(end);
            setBody(next);
            requestAnimationFrame(() => {
                el.selectionStart = el.selectionEnd = start + 2;
            });
        }
    };

    const toggleTag = (tag) => {
        setTags((prev) =>
            prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag]
        );
    };

    const handleSave = async () => {
        if (!title.trim()) return;
        setSaving(true);
        try {
            const today = new Date().toISOString().slice(0, 10);
            const excerpt = body
                .split(/\r?\n/)
                .find((l) => l.trim() && !l.startsWith('#'))
                ?.trim()
                .slice(0, 120) || '';
            await onSave({
                title: title.trim(),
                tags,
                body,
                excerpt,
                date: post?.date || today,
            });
            onClose();
        } finally {
            setSaving(false);
        }
    };

    // ESC 키로 닫기
    useEffect(() => {
        const handler = (e) => { if (e.key === 'Escape') onClose(); };
        document.addEventListener('keydown', handler);
        return () => document.removeEventListener('keydown', handler);
    }, [onClose]);

    return (
        <div className="blog-editor-overlay" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
            <div className="blog-editor">
                <div className="blog-editor__header">
                    <h2 className="blog-editor__heading">
                        {post?.id ? '글 수정' : '새 글 쓰기'}
                    </h2>
                    <button type="button" className="blog-editor__close" onClick={onClose} aria-label="닫기">
                        ✕
                    </button>
                </div>

                <input
                    className="blog-editor__title-input"
                    type="text"
                    placeholder="제목을 입력하세요"
                    value={title}
                    onChange={(e) => setTitle(e.target.value)}
                    autoFocus
                />

                <div className="blog-editor__tag-row">
                    {PRESET_TAGS.map((tag) => (
                        <button
                            key={tag}
                            type="button"
                            className={`blog-category-chip${tags.includes(tag) ? ' is-active' : ''}`}
                            onClick={() => toggleTag(tag)}
                        >
                            {tag}
                        </button>
                    ))}
                </div>

                <div className="blog-editor__tab-bar">
                    <button
                        type="button"
                        className={`blog-editor__tab${!showPreview ? ' is-active' : ''}`}
                        onClick={() => setShowPreview(false)}
                    >
                        편집
                    </button>
                    <button
                        type="button"
                        className={`blog-editor__tab${showPreview ? ' is-active' : ''}`}
                        onClick={() => setShowPreview(true)}
                    >
                        미리보기
                    </button>
                </div>

                {showPreview ? (
                    <div className="blog-article__body blog-editor__preview">
                        {body
                            ? renderMarkdown(body)
                            : <p style={{ color: 'var(--muted)' }}>본문을 입력하면 여기에 미리보기가 표시됩니다.</p>
                        }
                    </div>
                ) : (
                    <textarea
                        ref={textareaRef}
                        className="blog-editor__textarea"
                        placeholder="마크다운으로 글을 작성하세요...&#10;&#10;예시:&#10;# 제목&#10;## 소제목&#10;**굵게** *기울임* `코드`"
                        value={body}
                        onChange={(e) => setBody(e.target.value)}
                        onKeyDown={handleKeyDown}
                        spellCheck={false}
                    />
                )}

                <div className="blog-editor__footer">
                    <button type="button" className="button" onClick={onClose}>
                        취소
                    </button>
                    <button
                        type="button"
                        className="button blog-editor__save-btn"
                        onClick={handleSave}
                        disabled={saving || !title.trim()}
                    >
                        {saving ? '저장 중...' : '저장'}
                    </button>
                </div>
            </div>
        </div>
    );
};

// ── 메인 Blog 컴포넌트 ───────────────────────────────────────────────────────

const Blog = () => {
    const staticPosts = useMemo(() => getBlogPosts(), []);
    const [apiPosts, setApiPosts] = useState([]);
    const [apiError, setApiError] = useState(false);
    const [editorPost, setEditorPost] = useState(null); // null=닫힘, {}=새글, post=수정
    const [isEditorOpen, setIsEditorOpen] = useState(false);

    const fetchPosts = useCallback(() => {
        return getBlogPostsApi()
            .then((data) => {
                const posts = Array.isArray(data) ? data : (data?.posts ?? []);
                setApiPosts(posts.map((p) => ({ ...p, slug: `api-${p.id}` })));
            })
            .catch(() => setApiError(true));
    }, []);

    // API 글 불러오기
    useEffect(() => {
        fetchPosts();
    }, [fetchPosts]);

    // 정적 + API 글 병합 (API 글이 앞에 표시)
    const allPosts = useMemo(() => {
        const combined = [...apiPosts, ...staticPosts];
        return combined.sort((a, b) => {
            const aDate = Date.parse(a.date || '') || 0;
            const bDate = Date.parse(b.date || '') || 0;
            return bDate - aDate;
        });
    }, [apiPosts, staticPosts]);

    const categoryNames = ['일상', '개발', '공부', '아이디어'];
    const categorized = useMemo(() => {
        const map = new Map(categoryNames.map((name) => [name, []]));
        const misc = [];
        allPosts.forEach((post) => {
            const matched = categoryNames.find((name) => post.tags.includes(name));
            if (matched) map.get(matched).push(post);
            else misc.push(post);
        });
        return {
            categories: categoryNames.map((name) => ({ name, items: map.get(name) })),
            misc,
        };
    }, [allPosts]);

    const [selectedCategory, setSelectedCategory] = useState('전체');
    const [page, setPage] = useState(1);
    const [showList, setShowList] = useState(false);
    const pageSize = 10;

    const filteredPosts = useMemo(() => {
        if (selectedCategory === '전체') return allPosts;
        if (selectedCategory === '기타') return categorized.misc;
        return allPosts.filter((post) => post.tags.includes(selectedCategory));
    }, [allPosts, categorized.misc, selectedCategory]);

    const totalPages = Math.max(1, Math.ceil(filteredPosts.length / pageSize));
    const pagedPosts = filteredPosts.slice((page - 1) * pageSize, page * pageSize);

    const [activeSlug, setActiveSlug] = useState(pagedPosts[0]?.slug);
    const activePost = pagedPosts.find((p) => p.slug === activeSlug) || pagedPosts[0];

    useEffect(() => { if (page > totalPages) setPage(1); }, [page, totalPages]);
    useEffect(() => {
        if (!pagedPosts.find((p) => p.slug === activeSlug)) {
            setActiveSlug(pagedPosts[0]?.slug);
        }
    }, [pagedPosts, activeSlug]);
    useEffect(() => { setPage(1); }, [selectedCategory]);

    // 에디터 저장 핸들러
    const handleSave = useCallback(async (data) => {
        if (editorPost?.id) {
            // 수정
            const updated = await updateBlogPost(editorPost.id, data);
            setApiPosts((prev) =>
                prev.map((p) =>
                    p.id === editorPost.id ? { ...p, ...updated, slug: `api-${updated.id ?? editorPost.id}` } : p
                )
            );
        } else {
            // 새 글
            const created = await createBlogPost(data);
            setApiPosts((prev) => [{ ...created, slug: `api-${created.id}` }, ...prev]);
            setActiveSlug(`api-${created.id}`);
        }
    }, [editorPost]);

    // 삭제 핸들러
    const handleDelete = useCallback(async (post) => {
        if (!window.confirm(`"${post.title}" 글을 삭제하시겠습니까?`)) return;
        await deleteBlogPost(post.id);
        setApiPosts((prev) => prev.filter((p) => p.id !== post.id));
        if (activeSlug === post.slug) setActiveSlug(null);
    }, [activeSlug]);

    const openNewEditor = () => { setEditorPost({}); setIsEditorOpen(true); };
    const openEditEditor = (post) => { setEditorPost(post); setIsEditorOpen(true); };
    const closeEditor = useCallback(() => { setIsEditorOpen(false); setEditorPost(null); }, []);

    return (
        <PullToRefresh onRefresh={fetchPosts}>
        <div className="blog">
            <header className="blog-header">
                <div>
                    <p className="blog-kicker">Journal</p>
                    <h1>개인 블로그</h1>
                    <p className="blog-sub">
                        글을 작성하고 태그를 달아 정리하세요.
                    </p>
                </div>
                <div className="blog-header__actions">
                    <div className="blog-status">
                        <p className="blog-status__title">이번 주의 기록</p>
                        <p className="blog-status__desc">
                            손에 닿는 생각을 즉시 적어두고, 나중에 다시 꺼내어 다듬습니다.
                        </p>
                    </div>
                    <button type="button" className="blog-new-btn" onClick={openNewEditor}>
                        + 새 글 쓰기
                    </button>
                </div>
            </header>

            <div className="blog-grid">
                <button
                    type="button"
                    className="blog-toggle-list"
                    onClick={() => setShowList((prev) => !prev)}
                    aria-label="글 목록 토글"
                >
                    ☰
                </button>
                <aside className={`blog-list ${showList ? 'is-visible' : ''}`}>
                    <div className="blog-category-filter">
                        {['전체', ...categoryNames, '기타'].map((name) => (
                            <button
                                key={name}
                                type="button"
                                className={`blog-category-chip${selectedCategory === name ? ' is-active' : ''}`}
                                onClick={() => setSelectedCategory(name)}
                            >
                                {name}
                            </button>
                        ))}
                    </div>

                    {pagedPosts.map((post) => (
                        <div
                            key={post.slug}
                            className={`blog-list__item-wrap${post.slug === activeSlug ? ' is-active' : ''}`}
                        >
                            <button
                                type="button"
                                className="blog-list__item-btn"
                                onClick={() => {
                                    setActiveSlug(post.slug);
                                    setShowList(false);
                                }}
                            >
                                <p className="blog-list__title">{post.title}</p>
                                <p className="blog-list__excerpt">{post.excerpt}</p>
                                <span className="blog-list__meta">{post.date || '작성일 미정'}</span>
                            </button>
                            {post.id && (
                                <div className="blog-list__actions">
                                    <button
                                        type="button"
                                        className="blog-list__action-btn"
                                        title="수정"
                                        onClick={() => openEditEditor(post)}
                                    >
                                        편집
                                    </button>
                                    <button
                                        type="button"
                                        className="blog-list__action-btn blog-list__action-btn--del"
                                        title="삭제"
                                        onClick={() => handleDelete(post)}
                                    >
                                        삭제
                                    </button>
                                </div>
                            )}
                        </div>
                    ))}

                    <div className="blog-pagination">
                        <button
                            type="button"
                            className="blog-page-btn"
                            onClick={() => setPage((prev) => Math.max(1, prev - 1))}
                            disabled={page === 1}
                        >
                            이전
                        </button>
                        <span className="blog-page-indicator">{page} / {totalPages}</span>
                        <button
                            type="button"
                            className="blog-page-btn"
                            onClick={() => setPage((prev) => Math.min(totalPages, prev + 1))}
                            disabled={page === totalPages}
                        >
                            다음
                        </button>
                    </div>
                </aside>

                <article className="blog-article">
                    {activePost ? (
                        <>
                            <div className="blog-article__meta">
                                <span>{activePost.date || '작성일 미정'}</span>
                                <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
                                    {activePost.tags.length > 0 && (
                                        <span className="blog-tags">
                                            {activePost.tags.map((tag) => (
                                                <span key={tag} className="blog-tag">{tag}</span>
                                            ))}
                                        </span>
                                    )}
                                    {activePost.id && (
                                        <button
                                            type="button"
                                            className="blog-article__edit-btn"
                                            onClick={() => openEditEditor(activePost)}
                                        >
                                            편집
                                        </button>
                                    )}
                                </div>
                            </div>
                            <div className="blog-article__body">
                                {renderMarkdown(activePost.body)}
                            </div>
                        </>
                    ) : (
                        <p className="blog-empty">
                            {apiError
                                ? '블로그 API에 연결할 수 없습니다. 백엔드 서버를 확인해 주세요.'
                                : '아직 작성된 글이 없습니다. 새 글 쓰기 버튼으로 첫 글을 작성해 보세요.'}
                        </p>
                    )}
                </article>
            </div>

            <section className="blog-categories">
                <div className="blog-categories__head">
                    <h2>카테고리</h2>
                    <p>태그 기준으로 글을 묶어 한눈에 확인할 수 있습니다.</p>
                </div>
                <div className="blog-categories__grid">
                    {categorized.categories.map((group) => (
                        <button
                            key={group.name}
                            type="button"
                            className="blog-category-card"
                            onClick={() => setSelectedCategory(group.name)}
                        >
                            <div className="blog-category-card__head">
                                <span>{group.name}</span>
                                <span className="blog-category-card__count">{group.items.length}건</span>
                            </div>
                            <div className="blog-category-card__list">
                                {group.items.length ? (
                                    group.items.slice(0, 3).map((post) => (
                                        <span key={post.slug}>{post.title}</span>
                                    ))
                                ) : (
                                    <span className="blog-category-card__empty">아직 글이 없습니다.</span>
                                )}
                            </div>
                        </button>
                    ))}
                    <button
                        type="button"
                        className="blog-category-card"
                        onClick={() => setSelectedCategory('기타')}
                    >
                        <div className="blog-category-card__head">
                            <span>기타</span>
                            <span className="blog-category-card__count">{categorized.misc.length}건</span>
                        </div>
                        <div className="blog-category-card__list">
                            {categorized.misc.length ? (
                                categorized.misc.slice(0, 3).map((post) => (
                                    <span key={post.slug}>{post.title}</span>
                                ))
                            ) : (
                                <span className="blog-category-card__empty">아직 글이 없습니다.</span>
                            )}
                        </div>
                    </button>
                </div>
            </section>

            {isEditorOpen && (
                <BlogEditor
                    post={editorPost}
                    onSave={handleSave}
                    onClose={closeEditor}
                />
            )}

            <FAB onClick={openNewEditor} label="글 쓰기" />
        </div>
        </PullToRefresh>
    );
};

export default Blog;
