'use client'

import { useEffect, useMemo, useState } from 'react'
import { createPortal } from 'react-dom'
import { useTranslation } from 'react-i18next'
import { FiChevronLeft, FiChevronRight, FiX } from 'react-icons/fi'
import AvatarWithFrame, { AVATAR_FRAME_RING_PX } from '@/components/AvatarWithFrame'
import { toAvatarFramePayload } from '@/lib/avatarFrames/resolveUrl'
import type { UserAvatarFrameListItem } from '@/lib/avatarFrames/types'

/** 手機 2×3；桌面 md 以上 4×2 */
const MOBILE_PAGE_SIZE = 6
const DESKTOP_PAGE_SIZE = 8

function useCollectionPageSize(): number {
    const [pageSize, setPageSize] = useState(MOBILE_PAGE_SIZE)

    useEffect(() => {
        const mq = window.matchMedia('(min-width: 768px)')
        const update = () => setPageSize(mq.matches ? DESKTOP_PAGE_SIZE : MOBILE_PAGE_SIZE)
        update()
        mq.addEventListener('change', update)
        return () => mq.removeEventListener('change', update)
    }, [])

    return pageSize
}

function CollectionGridItem({
    frame,
    avatarSrc,
    alt,
    equippedLabel,
    useLabel,
    unequipLabel,
    canManage,
    actionLoading,
    onUse,
    onUnequip,
}: {
    frame: UserAvatarFrameListItem
    avatarSrc?: string | null
    alt: string
    equippedLabel: string
    useLabel: string
    unequipLabel: string
    canManage: boolean
    actionLoading: boolean
    onUse: (frameId: string) => void
    onUnequip: () => void
}) {
    return (
        <div className="flex flex-col items-center px-1">
            <div
                className="shrink-0"
                style={{
                    width: AVATAR_FRAME_RING_PX,
                    height: AVATAR_FRAME_RING_PX,
                    minWidth: AVATAR_FRAME_RING_PX,
                    minHeight: AVATAR_FRAME_RING_PX,
                }}
            >
                <AvatarWithFrame avatarSrc={avatarSrc} alt={alt} frame={toAvatarFramePayload(frame)} />
            </div>
            <div className="w-full min-w-0 px-0.5">
                <p className="flex min-h-[22px] w-full min-w-0 items-center justify-center gap-1.5 text-[13px] font-semibold leading-snug">
                    <span className="min-w-0 truncate text-gray-900 dark:text-white" title={frame.name}>
                        {frame.name}
                    </span>
                    {frame.isUsed ? (
                        <span className="inline-flex shrink-0 items-center rounded-full bg-emerald-500/15 px-2 py-0.5 text-[11px] font-medium text-emerald-700 ring-1 ring-emerald-500/30 dark:text-emerald-300">
                            {equippedLabel}
                        </span>
                    ) : null}
                </p>
            </div>
            {canManage ? (
                <button
                    type="button"
                    disabled={actionLoading}
                    onClick={() => (frame.isUsed ? onUnequip() : onUse(frame.id))}
                    className={`mt-3 w-full max-w-[166px] rounded-full py-2 text-xs font-semibold transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${
                        frame.isUsed
                            ? 'bg-neutral-900 text-white hover:bg-neutral-800 dark:bg-white dark:text-neutral-900 dark:hover:bg-neutral-200'
                            : 'bg-gray-100 text-gray-700 hover:bg-gray-200 dark:bg-white/10 dark:text-gray-100 dark:hover:bg-white/15'
                    }`}
                >
                    {frame.isUsed ? unequipLabel : useLabel}
                </button>
            ) : null}
        </div>
    )
}

export default function UserAvatarFrameCollectionModal({
    open,
    onClose,
    frames,
    loading,
    error,
    avatarSrc,
    displayName,
    title,
    emptyText,
    closeLabel,
    countLabel,
    equippedLabel,
    loadingText,
    useLabel,
    unequipLabel,
    canManage = false,
    actionLoading = false,
    onUse,
    onUnequip,
}: {
    open: boolean
    onClose: () => void
    frames: UserAvatarFrameListItem[] | null
    loading: boolean
    error: string | null
    avatarSrc?: string | null
    displayName: string
    title: string
    emptyText: string
    closeLabel: string
    countLabel: (count: number) => string
    equippedLabel: string
    loadingText: string
    useLabel: string
    unequipLabel: string
    canManage?: boolean
    actionLoading?: boolean
    onUse: (frameId: string) => void
    onUnequip: () => void
}) {
    const { t } = useTranslation()
    const pageSize = useCollectionPageSize()
    const [mounted, setMounted] = useState(false)
    const [page, setPage] = useState(1)

    useEffect(() => {
        setMounted(true)
    }, [])

    useEffect(() => {
        if (open) setPage(1)
    }, [open])

    useEffect(() => {
        const total = Math.max(1, Math.ceil((frames?.length ?? 0) / pageSize))
        setPage((p) => Math.min(p, total))
    }, [frames, pageSize])

    useEffect(() => {
        if (!open) return
        const prev = document.body.style.overflow
        document.body.style.overflow = 'hidden'
        return () => {
            document.body.style.overflow = prev
        }
    }, [open])

    const list = frames ?? []
    const totalPages = Math.max(1, Math.ceil(list.length / pageSize))
    const currentPage = Math.min(page, totalPages)
    const pageStart = (currentPage - 1) * pageSize
    const pageItems = list.slice(pageStart, pageStart + pageSize)
    const pageGridSlots = useMemo(() => {
        const slots: (UserAvatarFrameListItem | null)[] = [...pageItems]
        while (slots.length < pageSize) {
            slots.push(null)
        }
        return slots
    }, [pageItems, pageSize])
    const showPagination = !loading && !error && list.length > pageSize

    if (!mounted || !open) return null

    return createPortal(
        <div
            className="fixed inset-0 z-[320] flex items-stretch justify-center sm:items-center sm:p-6"
            role="dialog"
            aria-modal="true"
            aria-label={title}
        >
            <div className="absolute inset-0 bg-black/50 sm:bg-black/55" aria-hidden />
            <div
                className="relative z-10 flex h-full w-full min-h-0 flex-col overflow-hidden bg-white shadow-2xl dark:bg-[#0c0d0e] sm:h-auto sm:max-h-[min(90vh,820px)] sm:max-w-[900px] sm:rounded-2xl sm:border sm:border-gray-200 dark:sm:border-white/10"
            >
                <header className="flex shrink-0 items-start justify-between gap-3 px-5 pt-4 sm:px-8">
                    <div className="min-w-0 pr-2">
                        <h2 className="text-xl font-bold leading-tight text-gray-900 dark:text-white sm:text-2xl">
                            {title}
                        </h2>
                        {!loading && !error ? (
                            <p className="mt-1.5 text-sm text-gray-500 dark:text-gray-400">
                                {countLabel(list.length)}
                            </p>
                        ) : null}
                    </div>
                    <div className="flex shrink-0 items-center gap-1">
                        <button
                            type="button"
                            onClick={onClose}
                            className="inline-flex h-9 w-9 items-center justify-center rounded-full text-gray-500 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-white/10"
                            aria-label={closeLabel}
                        >
                            <FiX className="h-6 w-6" strokeWidth={2} />
                        </button>
                    </div>
                </header>

                <div className="flex min-h-0 flex-1 flex-col">
                    <div className="min-h-0 flex-1 overflow-y-auto px-5 sm:px-8">
                    {loading ? (
                        <div className="flex min-h-[240px] items-center justify-center text-sm text-gray-500 dark:text-gray-400">
                            {loadingText}
                        </div>
                    ) : error ? (
                        <p className="py-12 text-center text-sm text-red-500 dark:text-red-400">{error}</p>
                    ) : list.length === 0 ? (
                        <p className="py-12 text-center text-sm text-gray-500 dark:text-gray-400">{emptyText}</p>
                    ) : (
                        <div className="grid grid-cols-2 auto-rows-fr gap-x-3 gap-y-8 py-4 md:grid-cols-4 md:gap-x-6 md:gap-y-10">
                            {pageGridSlots.map((frame, index) =>
                                frame ? (
                                    <CollectionGridItem
                                        key={frame.id}
                                        frame={frame}
                                        avatarSrc={avatarSrc}
                                        alt={displayName}
                                        equippedLabel={equippedLabel}
                                        useLabel={useLabel}
                                        unequipLabel={unequipLabel}
                                        canManage={canManage}
                                        actionLoading={actionLoading}
                                        onUse={onUse}
                                        onUnequip={onUnequip}
                                    />
                                ) : (
                                    <div key={`avatar-frame-slot-empty-${index}`} className="min-h-[1px]" aria-hidden />
                                ),
                            )}
                        </div>
                    )}
                    </div>
                    {showPagination ? (
                        <footer className="flex shrink-0 items-center justify-center gap-4 border-t border-gray-200 px-5 py-4 dark:border-white/10 sm:px-8">
                            <button
                                type="button"
                                disabled={currentPage <= 1}
                                onClick={() => setPage((p) => Math.max(1, p - 1))}
                                className="inline-flex h-9 w-9 items-center justify-center rounded-full text-gray-600 transition-colors hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-40 dark:text-gray-300 dark:hover:bg-white/10"
                                aria-label={t('common.previous')}
                            >
                                <FiChevronLeft className="h-5 w-5" strokeWidth={2} />
                            </button>
                            <span className="min-w-[4.5rem] text-center text-sm font-medium tabular-nums text-gray-700 dark:text-gray-200">
                                {t('user.avatarFrames.page', { current: currentPage, total: totalPages })}
                            </span>
                            <button
                                type="button"
                                disabled={currentPage >= totalPages}
                                onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
                                className="inline-flex h-9 w-9 items-center justify-center rounded-full text-gray-600 transition-colors hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-40 dark:text-gray-300 dark:hover:bg-white/10"
                                aria-label={t('common.next')}
                            >
                                <FiChevronRight className="h-5 w-5" strokeWidth={2} />
                            </button>
                        </footer>
                    ) : (
                        <div className="shrink-0 pb-8 sm:pb-10" aria-hidden />
                    )}
                </div>
            </div>
        </div>,
        document.body
    )
}
