import { type FC, useRef, useCallback, useState, useEffect, useLayoutEffect, useMemo, useSyncExternalStore } from 'react';
import HTMLFlipBook from 'react-pageflip';
import { type PageData } from '../types';
import BookPage from './BookPage';
import { ArrowLeft2, ArrowRight2, Pause, Play } from 'iconsax-react';
import { getPaperDimensions } from '@/config/paperSizes';
import type { DocumentSettings } from '@/pages/editor/store/editorStore';

/** فاصله پیش‌فرض بین هر ورق در پخش خودکار (میلی‌ثانیه) */
const AUTO_PLAY_INTERVAL_MS = 3000;

const VIEWER_SCALE = 0.5;
/** نسخهٔ فعلی `page-flip.mp3` دو ضربهٔ ورق پشت‌هم دارد؛ فقط تا این سهم از طول پخش می‌شود */
const PAGE_FLIP_SOUND_PLAY_FRACTION = 0.5;
/** هم‌راستا با `md` تیلویند (768px) — موبایل: زیر این عرض */
const MOBILE_QUERY = '(min-width: 768px)';

function subscribeDesktopMql(callback: () => void) {
    const mq = window.matchMedia(MOBILE_QUERY);
    mq.addEventListener('change', callback);
    return () => mq.removeEventListener('change', callback);
}

function useIsDesktop() {
    return useSyncExternalStore(
        subscribeDesktopMql,
        () => window.matchMedia(MOBILE_QUERY).matches,
        () => true
    );
}

export type BookViewerProps = {
    pages: PageData[];
    catalogSize?: string;
    documentSettings?: Partial<DocumentSettings>;
};

interface PageFlipAPI {
    flipNext: () => void;
    flipPrev: () => void;
    turnToPage: (page: number) => void;
    getCurrentPageIndex?: () => number;
}

interface FlipBookInstance {
    pageFlip: () => PageFlipAPI | undefined;
}

interface FlipEvent {
    data: number;
}

type PageFlipInitEvent = { data: { page: number; mode: string } };
type PageFlipStateEvent = { data: string };

/** مختصات داخلی رندر کتاب (همان فضایی که getBoundsRect و flipNext استفاده می‌کنند) */
type FlipBookRect = { left: number; top: number; width: number; height: number; pageWidth: number };

type PageFlipWithFlipController = PageFlipAPI & {
    getBoundsRect: () => FlipBookRect;
    getFlipController: () => { flip: (p: { x: number; y: number }) => void };
};

type AutoPlayToggleButtonProps = {
    isActive: boolean;
    onToggle: () => void;
};

const AutoPlayToggleButton: FC<AutoPlayToggleButtonProps> = ({ isActive, onToggle }) => (
    <button
        type="button"
        onClick={onToggle}
        className="px-3 py-1.5 text-xs md:text-sm font-medium inline-flex items-center justify-center gap-1.5 rounded-full border border-gray-300 hover:bg-gray-100 active:bg-gray-200 transition-all"
        aria-label={isActive ? 'توقف پخش خودکار' : 'شروع پخش خودکار'}
    >
        {isActive ? (
            <Pause color='black' size={16} className="text-gray-700 md:w-[18px] md:h-[18px]" />
        ) : (
            <Play color='black' size={16} className="text-gray-700 md:w-[18px] md:h-[18px]" />
        )}
        <span>{isActive ? 'توقف پخش' : 'پخش خودکار'}</span>
    </button>
);

/**
 * page-flip داخل flipPrev با x=10 ثابت می‌زند؛ با disableFlipByClick آزمایش گوشه رد می‌شود
 * (چون bookPos.x = 10 - rect.left معمولاً ≤ 0). flipNext همان rect.left را جمع می‌کند.
 */
function triggerFlipPrev(api: PageFlipWithFlipController | undefined) {
    if (!api?.getBoundsRect || !api.getFlipController) {
        api?.flipPrev();
        return;
    }
    const rect = api.getBoundsRect();
    api.getFlipController().flip({
        x: rect.left + 12,
        y: rect.top + 2,
    });
}

/**
 * کامپوننت اصلی کتابخوان با استفاده از react-pageflip
 * این کامپوننت از HTMLFlipBook استفاده می‌کند که یک wrapper برای PageFlip است
 * از HTML برای رندر صفحات استفاده می‌شود (نه Canvas) برای سازگاری با Konva در آینده
 */
const BookViewer: FC<BookViewerProps> = ({ pages, catalogSize, documentSettings }) => {
    const bookRef = useRef<FlipBookInstance | null>(null);
    const pageFlipHandlerRef = useRef<(e: FlipEvent) => void>(() => { });
    const [currentPage, setCurrentPage] = useState(0);
    const [isAutoPlayActive, setIsAutoPlayActive] = useState(false);
    const [startPage, setStartPage] = useState(0);
    const isDesktop = useIsDesktop();

    const autoPlay = documentSettings?.autoPlay ?? false;
    const pageFlipSound = documentSettings?.pageFlipSound ?? true;
    const leftToRightFlip = documentSettings?.leftToRightFlip ?? false;
    const displayStyle = documentSettings?.displayStyle ?? 'double';
    const backgroundType = documentSettings?.backgroundType ?? 'color';
    const backgroundColor = documentSettings?.backgroundColor ?? '#ffffff';
    const backgroundImageUrl = documentSettings?.backgroundImageUrl ?? '';

    useEffect(() => {
        setIsAutoPlayActive(autoPlay);
    }, [autoPlay]);

    // سایز کتاب بر اساس catalogSize (A3/A4/A5)
    const { width: bookWidth, height: bookHeight } = useMemo(
        () => getPaperDimensions(catalogSize ?? 'a4'),
        [catalogSize]
    );
    const displayWidth = Math.round(bookWidth * VIEWER_SCALE);
    const displayHeight = Math.round(bookHeight * VIEWER_SCALE);
    const hasMultiplePages = pages.length > 1;

    // موبایل: از ابعاد viewport برای جا دادن کتاب در صفحه
    const [viewport, setViewport] = useState(() =>
        typeof window !== 'undefined'
            ? { w: window.innerWidth, h: window.innerHeight }
            : { w: 1200, h: 800 }
    );
    useLayoutEffect(() => {
        const onResize = () => setViewport({ w: window.innerWidth, h: window.innerHeight });
        onResize();
        window.addEventListener('resize', onResize);
        window.addEventListener('orientationchange', onResize);
        return () => {
            window.removeEventListener('resize', onResize);
            window.removeEventListener('orientationchange', onResize);
        };
    }, []);

    const mobileFit = useMemo(() => {
        if (isDesktop) return null;
        const padX = 20;
        const edgeBleed = 6;
        const reservedNav = 120;
        const maxW = Math.max(1, viewport.w - padX - edgeBleed * 2);
        const maxH = Math.max(1, viewport.h - reservedNav - edgeBleed);
        const baseW = bookWidth * VIEWER_SCALE;
        const baseH = bookHeight * VIEWER_SCALE;
        const scale = Math.min(1, maxW / baseW, maxH / baseH);
        return {
            w: Math.max(1, Math.round(baseW * scale)),
            h: Math.max(1, Math.round(baseH * scale)),
            contentScale: VIEWER_SCALE * scale,
        };
    }, [isDesktop, bookWidth, bookHeight, viewport.w, viewport.h]);

    // دسکتاپ: دقیقاً مثل قبل — موبایل: مقیاس‌شده
    const pagePixelWidth = isDesktop ? displayWidth : (mobileFit?.w ?? displayWidth);
    const pagePixelHeight = isDesktop ? displayHeight : (mobileFit?.h ?? displayHeight);
    const contentScale = isDesktop ? VIEWER_SCALE : (mobileFit?.contentScale ?? VIEWER_SCALE);

    const flipKey = isDesktop
        ? 'desktop'
        : `mobile-${pagePixelWidth}-${pagePixelHeight}`;

    // اطمینان از اینکه currentPage همیشه در محدوده معتبر است
    useEffect(() => {
        if (currentPage < 0) {
            setCurrentPage(0);
        } else if (currentPage >= pages.length) {
            setCurrentPage(pages.length - 1);
        }
    }, [currentPage, pages.length]);

    const pageFlipSoundRef = useRef<HTMLAudioElement | null>(null);
    const pageFlipSoundTrimListenerRef = useRef<(() => void) | null>(null);
    const lastFlipPageRef = useRef<number | null>(null);

    useEffect(() => {
        const base = import.meta.env.BASE_URL;
        const src = `${base}${base.endsWith('/') ? '' : '/'}sounds/page-flip.mp3`;
        const audio = new Audio(src);
        audio.preload = 'auto';
        pageFlipSoundRef.current = audio;
        return () => {
            const trim = pageFlipSoundTrimListenerRef.current;
            if (trim) {
                audio.removeEventListener('timeupdate', trim);
                pageFlipSoundTrimListenerRef.current = null;
            }
            audio.pause();
            pageFlipSoundRef.current = null;
        };
    }, []);

    const playPageFlipSound = useCallback(() => {
        const audio = pageFlipSoundRef.current;
        if (!audio) return;
        const prevTrim = pageFlipSoundTrimListenerRef.current;
        if (prevTrim) {
            audio.removeEventListener('timeupdate', prevTrim);
            pageFlipSoundTrimListenerRef.current = null;
        }
        const onTimeUpdate = () => {
            const d = audio.duration;
            if (!Number.isFinite(d) || d <= 0.04) return;
            const end = d * PAGE_FLIP_SOUND_PLAY_FRACTION;
            if (audio.currentTime >= end) {
                audio.pause();
                audio.currentTime = 0;
                audio.removeEventListener('timeupdate', onTimeUpdate);
                pageFlipSoundTrimListenerRef.current = null;
            }
        };
        pageFlipSoundTrimListenerRef.current = onTimeUpdate;
        try {
            audio.currentTime = 0;
            audio.addEventListener('timeupdate', onTimeUpdate);
            void audio.play().catch(() => {
                audio.removeEventListener('timeupdate', onTimeUpdate);
                pageFlipSoundTrimListenerRef.current = null;
                /* autoplay policy — معمولاً بعد از تعامل کاربر ورق می‌خورد */
            });
        } catch {
            audio.removeEventListener('timeupdate', onTimeUpdate);
            pageFlipSoundTrimListenerRef.current = null;
        }
    }, []);

    const handlePageFlip = useCallback((e: FlipEvent) => {
        // react-pageflip شماره صفحه را به صورت 0-based برمی‌گرداند
        // اما باید مطمئن شویم که در محدوده معتبر است
        let pageNum = e.data;

        // اگر pageNum منفی است یا بزرگتر از تعداد صفحات، آن را محدود می‌کنیم
        if (pageNum < 0) {
            pageNum = 0;
        } else if (pageNum >= pages.length) {
            pageNum = pages.length - 1;
        }

        if (pageFlipSound && lastFlipPageRef.current !== null && lastFlipPageRef.current !== pageNum) {
            playPageFlipSound();
        }
        lastFlipPageRef.current = pageNum;

        setCurrentPage(pageNum);
    }, [pages.length, pageFlipSound, playPageFlipSound]);

    pageFlipHandlerRef.current = handlePageFlip;

    const onFlipForwarded = useCallback((e: FlipEvent) => {
        pageFlipHandlerRef.current(e);
    }, []);

    const syncPageIndexFromBook = useCallback(() => {
        const api = bookRef.current?.pageFlip();
        const idx = api?.getCurrentPageIndex?.();
        if (typeof idx !== 'number' || pages.length <= 0) return;
        const clamped = Math.max(0, Math.min(idx, pages.length - 1));
        setCurrentPage(clamped);
    }, [pages.length]);

    const handleBookInit = useCallback(
        (e: PageFlipInitEvent) => {
            const p = e.data?.page;
            if (typeof p !== 'number' || pages.length <= 0) return;
            const clamped = Math.max(0, Math.min(p, pages.length - 1));
            setCurrentPage(clamped);
            lastFlipPageRef.current = clamped;
        },
        [pages.length]
    );

    /** بعد از اتمام انیمیشن، ایندکس واقعی کتاب را می‌گیریم (RTL روی روت کتاب مختصات page-flip را به‌هم می‌زند) */
    const handleChangeState = useCallback(
        (e: PageFlipStateEvent) => {
            if (e.data !== 'read') return;
            syncPageIndexFromBook();
        },
        [syncPageIndexFromBook]
    );

    const goToNextPage = useCallback(() => {
        if (currentPage < pages.length - 1) {
            bookRef.current?.pageFlip()?.flipNext();
        }
    }, [currentPage, pages.length]);

    const goToPrevPage = useCallback(() => {
        if (currentPage <= 0) return;
        const api = bookRef.current?.pageFlip() as PageFlipWithFlipController | undefined;
        triggerFlipPrev(api);
    }, [currentPage]);

    const stopAutoPlayByUser = useCallback(() => {
        if (isAutoPlayActive) {
            setIsAutoPlayActive(false);
        }
    }, [isAutoPlayActive]);

    const toggleAutoPlay = useCallback(() => {
        if (pages.length <= 1) return;
        setIsAutoPlayActive(prev => !prev);
    }, [pages.length]);

    const handleLinkClick = useCallback((linkUrl: string) => {
        if (pages.length <= 1) return;
        if (linkUrl.startsWith('page://')) {
            const action = linkUrl.replace('page://', '');
            const pageFlipAPI = bookRef.current?.pageFlip() as PageFlipWithFlipController | undefined;

            if (!pageFlipAPI) return;

            if (action === 'next') {
                goToNextPage();
            } else if (action === 'prev') {
                goToPrevPage();
            } else if (action === 'first') {
                // رفتن به صفحه اول
                const flipToFirst = () => {
                    if (currentPage > 0) {
                        triggerFlipPrev(pageFlipAPI);
                        setTimeout(() => {
                            setCurrentPage(prev => {
                                if (prev > 1) {
                                    flipToFirst();
                                }
                                return prev - 1;
                            });
                        }, 300);
                    }
                };
                flipToFirst();
            } else if (action === 'last') {
                // رفتن به صفحه آخر
                const lastPageIndex = pages.length - 1;
                const flipToLast = () => {
                    if (currentPage < lastPageIndex) {
                        pageFlipAPI.flipNext();
                        setTimeout(() => {
                            setCurrentPage(prev => {
                                if (prev < lastPageIndex - 1) {
                                    flipToLast();
                                }
                                return prev + 1;
                            });
                        }, 300);
                    }
                };
                flipToLast();
            } else {
                // شماره صفحه مشخص (مثل page://3)
                const pageNum = parseInt(action, 10);
                if (!isNaN(pageNum) && pageNum >= 1 && pageNum <= pages.length) {
                    const targetIndex = pageNum - 1;
                    const diff = targetIndex - currentPage;

                    const flipToTarget = (remaining: number) => {
                        if (remaining === 0) return;

                        if (remaining > 0) {
                            pageFlipAPI.flipNext();
                            setTimeout(() => {
                                setCurrentPage(prev => prev + 1);
                                flipToTarget(remaining - 1);
                            }, 300);
                        } else {
                            triggerFlipPrev(pageFlipAPI);
                            setTimeout(() => {
                                setCurrentPage(prev => prev - 1);
                                flipToTarget(remaining + 1);
                            }, 300);
                        }
                    };

                    flipToTarget(diff);
                }
            }
        }
    }, [currentPage, pages.length, goToNextPage, goToPrevPage]);

    // تک‌صفحه‌ای: موبایل یا تنظیم single، دوصفحه‌ای: دسکتاپ + تنظیم double
    const usePortrait = !isDesktop || displayStyle === 'single';

    const prevFlipKeyRef = useRef(flipKey);
    useEffect(() => {
        if (prevFlipKeyRef.current !== flipKey) {
            prevFlipKeyRef.current = flipKey;
            lastFlipPageRef.current = currentPage;
            setStartPage(currentPage);
        }
    }, [flipKey, currentPage]);

    // پخش خودکار
    useEffect(() => {
        if (!isAutoPlayActive || pages.length <= 1) return;
        const timer = setInterval(() => {
            if (currentPage >= pages.length - 1) {
                bookRef.current?.pageFlip()?.turnToPage?.(0);
                setCurrentPage(0);
                lastFlipPageRef.current = 0;
                return;
            }
            bookRef.current?.pageFlip()?.flipNext();
        }, AUTO_PLAY_INTERVAL_MS);
        return () => clearInterval(timer);
    }, [isAutoPlayActive, currentPage, pages.length]);

    return (
        <div
            className="flex flex-col items-center gap-4 md:gap-6 w-full h-full max-md:min-h-0 max-md:max-w-full max-md:overflow-x-hidden max-md:pb-[env(safe-area-inset-bottom,0px)]"
            dir="rtl"
        >
            <div
                className="relative w-full flex justify-center flex-1 max-md:min-h-0 items-center"
                style={{ overflow: isDesktop ? 'hidden' : 'visible' }}
            >
                {/* Border و Shadow عمودی در وسط (فقط حالت دوصفحه‌ای دسکتاپ) */}
                {!usePortrait && (
                    <div
                        className="hidden md:block absolute inset-y-0 left-1/2 -translate-x-1/2 w-px border-r border-gray-300 pointer-events-none z-50"
                        style={{
                            boxShadow: '-5px 0 15px rgba(0, 0, 0, 0.15), 5px 0 15px rgba(0, 0, 0, 0.15)',
                        }}
                    />
                )}
                {/*
                  page-flip با مختصات LTR کار می‌کند؛ direction:rtl روی روت کتاب باعث ناهماهنگی
                  ایندکس/onFlip با دکمه‌ها می‌شود. محتوای فارسی داخل BookPage با dir=rtl است.
                */}
                <div
                    dir="ltr"
                    className="max-w-full flex justify-center"
                    style={{ overflow: isDesktop ? 'hidden' : 'visible', isolation: 'isolate' }}
                >
                    <HTMLFlipBook
                        key={flipKey}
                        ref={bookRef}
                        width={pagePixelWidth}
                        height={pagePixelHeight}
                        size="fixed"
                        minWidth={pagePixelWidth}
                        minHeight={pagePixelHeight}
                        maxWidth={pagePixelWidth}
                        maxHeight={pagePixelHeight}
                        drawShadow={isDesktop}
                        flippingTime={800}
                        usePortrait={usePortrait}
                        startPage={startPage}
                        autoSize={false}
                        maxShadowOpacity={isDesktop ? 0.5 : 0}
                        showCover={hasMultiplePages}
                        mobileScrollSupport={!usePortrait}
                        clickEventForward={true}
                        useMouseEvents={hasMultiplePages}
                        swipeDistance={hasMultiplePages ? (usePortrait ? 48 : 30) : 9999}
                        startZIndex={1}
                        showPageCorners={hasMultiplePages}
                        disableFlipByClick={true}
                        className="flipbook-container mx-auto max-w-full"
                        style={{}}
                        onFlip={onFlipForwarded}
                        onInit={handleBookInit}
                        onChangeState={handleChangeState}
                    >
                        {pages.map((page) => (
                            <BookPage
                                key={page.id}
                                page={page}
                                scale={contentScale}
                                pageWidth={pagePixelWidth}
                                pageHeight={pagePixelHeight}
                                onLinkClick={handleLinkClick}
                                backgroundType={page.backgroundType ?? backgroundType}
                                backgroundColor={page.backgroundColor ?? backgroundColor}
                                backgroundImageUrl={page.backgroundImageUrl ?? backgroundImageUrl}
                            />
                        ))}
                    </HTMLFlipBook>
                </div>
            </div>

            <div className="shrink-0 max-md:min-h-12 flex items-center gap-3 md:gap-6 bg-white rounded-full px-4 md:px-6 py-2 md:py-3 shadow-lg">
                {hasMultiplePages && (
                    <>
                        {/* دکمه راست: فارسی = صفحه بعد | لاتین = صفحه قبل */}
                        <button
                            type="button"
                            onClick={() => {
                                stopAutoPlayByUser();
                                if (leftToRightFlip) {
                                    goToPrevPage();
                                } else {
                                    goToNextPage();
                                }
                            }}
                            disabled={leftToRightFlip ? currentPage <= 0 : currentPage >= pages.length - 1}
                            className="p-2 md:p-2 min-h-11 min-w-11 md:min-h-0 md:min-w-0 inline-flex items-center justify-center rounded-full hover:bg-gray-100 active:bg-gray-200 disabled:opacity-30 disabled:cursor-not-allowed transition-all"
                            aria-label={leftToRightFlip ? 'صفحه قبل' : 'صفحه بعد'}
                        >
                            <ArrowRight2 color='black' size={20} className="text-gray-700 md:w-6 md:h-6" />
                        </button>
                    </>
                )}

                {/* شماره صفحه */}
                <div className="flex items-center gap-2 min-w-[100px] md:min-w-[120px] justify-center">
                    <span className="text-xs md:text-sm text-gray-600">
                        صفحه {Math.min(currentPage + 1, pages.length)} از {pages.length}
                    </span>
                </div>



                {hasMultiplePages && (
                    <>
                        {/* دکمه چپ: فارسی = صفحه قبل | لاتین = صفحه بعد */}
                        <button
                            type="button"
                            onClick={() => {
                                stopAutoPlayByUser();
                                if (leftToRightFlip) {
                                    goToNextPage();
                                } else {
                                    goToPrevPage();
                                }
                            }}
                            disabled={leftToRightFlip ? currentPage >= pages.length - 1 : currentPage <= 0}
                            className="p-2 md:p-2 min-h-11 min-w-11 md:min-h-0 md:min-w-0 inline-flex items-center justify-center rounded-full hover:bg-gray-100 active:bg-gray-200 disabled:opacity-30 disabled:cursor-not-allowed transition-all"
                            aria-label={leftToRightFlip ? 'صفحه بعد' : 'صفحه قبل'}
                        >
                            <ArrowLeft2 color='black' size={20} className="text-gray-700 md:w-6 md:h-6" />
                        </button>
                    </>
                )}

                {hasMultiplePages && autoPlay && (
                    <AutoPlayToggleButton isActive={isAutoPlayActive} onToggle={toggleAutoPlay} />
                )}
            </div>
        </div>
    );
};

export default BookViewer;
