'use client'

import { useState, useEffect, useMemo, useRef, useCallback } from 'react'
import ConfirmModal from '@/components/ConfirmModal'
import Header from '@/components/Header'
import Sidebar from '@/components/Sidebar'
import Footer from '@/components/Footer'
import BackToTop from '@/components/BackToTop'
import LiveCard, { type LiveStream } from '@/components/LiveCard'
import UserBannerSkeleton from '@/app/user/_components/Skeletons/UserBannerSkeleton'
import { useTranslation } from 'react-i18next'
import Image from 'next/image'
import Link from 'next/link'
import { createPortal } from 'react-dom'
import type { ReactNode } from 'react'
import {
    FiUsers,
    FiUser,
    FiArrowLeft,
    FiChevronRight,
    FiUserPlus,
    FiFlag,
    FiMoreVertical,
} from 'react-icons/fi'
import {
    isGroupDeputyRole,
    isGroupLeaderRole,
    type GroupMemberAction,
} from '@/lib/groups/groupMemberRole'
import { MdVerified } from 'react-icons/md'
import { formatViews } from '@/utils/format'
import { resolveGroupRoleBadge } from '@/lib/groups/groupRoleBadge'
import { tipBelowOnlyClass } from '@/lib/ui/tipBelowOnlyClass'
import { resolveMediaUrl } from '@/lib/media/resolveMediaUrl'
import { hasValidImageSrc } from '@/lib/media/mediaGuards'
import ViewerCard from '@/app/room/_components/chat/ViewerCard'
import type { ParticipantItem, ViewerCardState } from '@/app/room/_components/types'

const DEFAULT_COVER = '/images/user/default_cover.png'

interface FamilyMember {
    id: string
    displayName: string
    avatar: string | null
    followersCount: number
    totalViewsCount: number
    role: string
}

interface FamilyLiveStream {
    roomId: string
    userId: string
    title: string
    viewers: number
    thumbnail: string | null
    startedAt: string | number | null
    isLive: boolean
    displayName: string
    avatar: string | null
}

interface FamilyData {
    id: string
    name: string
    avatar: string | null
    banner: string | null
    description: string | null
    isVerified?: boolean
    groupLevelExp?: number
    artistsCount: number
    membersCount: number
    createdAt: string | number
    updatedAt: string | number
    members: FamilyMember[]
    liveStreams: FamilyLiveStream[]
}

interface FamilyDetailPageClientProps {
    groupId: string
    initialData: FamilyData | null
    currentUserId?: string | null
    canManageMembers?: boolean
}

function GroupAvatar({ avatar, name, className }: { avatar: string | null; name: string; className?: string }) {
    const src = resolveMediaUrl(avatar)
    const showImg = hasValidImageSrc(src)

    return (
        <div
            className={
                className ??
                'relative z-20 h-[88px] w-[88px] shrink-0 overflow-hidden rounded-2xl border-2 border-white bg-gray-100 shadow-md dark:border-white/20 dark:bg-neutral-800 sm:h-[104px] sm:w-[104px] md:h-[120px] md:w-[120px]'
            }
        >
            {showImg ? (
                // eslint-disable-next-line @next/next/no-img-element
                <img src={src} alt={name} className="h-full w-full object-cover" loading="lazy" decoding="async" />
            ) : (
                <span className="flex h-full w-full items-center justify-center text-gray-400 dark:text-gray-500">
                    <FiUsers className="h-10 w-10 sm:h-12 sm:w-12" strokeWidth={1.75} aria-hidden />
                </span>
            )}
        </div>
    )
}

function MemberCardMenu({
    member,
    t,
    onAction,
}: {
    member: FamilyMember
    t: (key: string) => string
    onAction: (member: FamilyMember, action: GroupMemberAction) => void | Promise<void>
}) {
    const [menuOpen, setMenuOpen] = useState(false)
    const [menuPos, setMenuPos] = useState({ top: 0, left: 0 })
    const triggerRef = useRef<HTMLButtonElement>(null)
    const menuPanelRef = useRef<HTMLDivElement>(null)

    const updateMenuPosition = useCallback(() => {
        const el = triggerRef.current
        if (!el) return
        const rect = el.getBoundingClientRect()
        setMenuPos({ top: rect.bottom + 4, left: rect.right })
    }, [])

    useEffect(() => {
        if (!menuOpen) return
        updateMenuPosition()
        const onDocMouseDown = (e: MouseEvent) => {
            const target = e.target as Node
            if (triggerRef.current?.contains(target) || menuPanelRef.current?.contains(target)) {
                return
            }
            setMenuOpen(false)
        }
        const onReposition = () => updateMenuPosition()
        document.addEventListener('mousedown', onDocMouseDown)
        window.addEventListener('resize', onReposition)
        window.addEventListener('scroll', onReposition, true)
        return () => {
            document.removeEventListener('mousedown', onDocMouseDown)
            window.removeEventListener('resize', onReposition)
            window.removeEventListener('scroll', onReposition, true)
        }
    }, [menuOpen, updateMenuPosition])

    const isLeader = isGroupLeaderRole(member.role)
    const isDeputy = isGroupDeputyRole(member.role)

    const items: Array<{ action: GroupMemberAction; label: string; danger?: boolean }> = []
    if (!isLeader) {
        items.push({ action: 'transfer_leader', label: t('familys.memberMenu.transferLeader') })
    }
    if (isDeputy) {
        items.push({ action: 'demote_member', label: t('familys.memberMenu.demoteMember') })
    }
    if (!isLeader && !isDeputy) {
        items.push({ action: 'promote_deputy', label: t('familys.memberMenu.promoteDeputy') })
    }
    items.push({ action: 'kick', label: t('familys.memberMenu.kick'), danger: true })

    const menuPanel =
        menuOpen && typeof document !== 'undefined' ? (
            <div
                ref={menuPanelRef}
                role="menu"
                className="fixed z-[200] min-w-[168px] overflow-hidden rounded-lg border border-gray-200 bg-white py-1 shadow-lg dark:border-gray-700 dark:bg-[#0c0d0e]"
                style={{
                    top: menuPos.top,
                    left: menuPos.left,
                    transform: 'translateX(-100%)',
                }}
            >
                {items.map((item) => (
                    <button
                        key={item.action}
                        type="button"
                        role="menuitem"
                        onClick={(e) => {
                            e.stopPropagation()
                            setMenuOpen(false)
                            void onAction(member, item.action)
                        }}
                        className={`block w-full px-3.5 py-2 text-left text-sm transition-colors ${
                            item.danger
                                ? 'text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-950/40'
                                : 'text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-[#1a1c21]'
                        }`}
                    >
                        {item.label}
                    </button>
                ))}
            </div>
        ) : null

    return (
        <>
            <button
                ref={triggerRef}
                type="button"
                onClick={(e) => {
                    e.stopPropagation()
                    if (menuOpen) {
                        setMenuOpen(false)
                    } else {
                        updateMenuPosition()
                        setMenuOpen(true)
                    }
                }}
                className={`inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-gray-500 transition-[opacity,background-color] duration-150 hover:bg-gray-200/80 dark:text-gray-400 dark:hover:bg-white/10 [@media(hover:hover)]:opacity-0 [@media(hover:hover)]:group-hover:opacity-100 focus-visible:opacity-100 [@media(hover:none)]:opacity-100 ${menuOpen ? 'opacity-100' : ''}`}
                aria-label={t('familys.memberMenu.moreOptions')}
                aria-expanded={menuOpen}
                aria-haspopup="menu"
            >
                <FiMoreVertical className="h-4 w-4" aria-hidden />
            </button>
            {menuPanel && createPortal(menuPanel, document.body)}
        </>
    )
}

function MemberCard({
    member,
    t,
    onSelect,
    canManage,
    onMemberAction,
}: {
    member: FamilyMember
    t: (key: string) => string
    onSelect: (member: FamilyMember) => void
    canManage: boolean
    onMemberAction: (member: FamilyMember, action: GroupMemberAction) => void | Promise<void>
}) {
    const avatarSrc = resolveMediaUrl(member.avatar)
    const showAvatar = hasValidImageSrc(avatarSrc)

    return (
        <div className="group flex items-center gap-3 rounded-xl bg-gray-50/90 p-3 dark:bg-white/[0.04] sm:p-3.5">
            <button
                type="button"
                onClick={() => onSelect(member)}
                className="relative h-12 w-12 shrink-0 overflow-hidden rounded-full bg-gray-200 ring-2 ring-white transition-opacity hover:opacity-90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-400 dark:bg-neutral-800 dark:ring-[#0c0d0e] dark:focus-visible:outline-white/50 sm:h-14 sm:w-14"
                aria-label={member.displayName}
            >
                {showAvatar ? (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img
                        src={avatarSrc}
                        alt=""
                        className="h-full w-full object-cover"
                        loading="lazy"
                        decoding="async"
                    />
                ) : (
                    <span className="flex h-full w-full items-center justify-center text-gray-400">
                        <FiUser className="h-6 w-6" aria-hidden />
                    </span>
                )}
            </button>
            <div className="min-w-0 flex-1">
                <div className="flex min-w-0 items-center gap-2">
                    <span className="truncate text-sm font-semibold text-gray-900 dark:text-gray-100 sm:text-base">
                        {member.displayName}
                    </span>
                    <MemberRoleBadge role={member.role} t={t} />
                </div>
                <p className="mt-1 flex items-center gap-1 text-xs text-gray-500 dark:text-gray-400">
                    <FiUser className="h-3 w-3 shrink-0 opacity-70" aria-hidden />
                    <span>
                        {formatViews(member.followersCount)} {t('familys.followers')}
                    </span>
                </p>
            </div>
            {canManage ? (
                <MemberCardMenu member={member} t={t} onAction={onMemberAction} />
            ) : null}
        </div>
    )
}

const GROUP_ROLE_ICON = {
    leader: '/images/group/host.png',
    deputy: '/images/group/deputy_host.png',
} as const

/** 原圖 1210×900；顯示 16px 高，請求 2x 尺寸由 next/image 縮放以避免瀏覽器縮小整張圖發糊 */
const GROUP_ROLE_ICON_DISPLAY_H = 16
const GROUP_ROLE_ICON_ASPECT = 1210 / 900
const GROUP_ROLE_ICON_DISPLAY_W = Math.round(GROUP_ROLE_ICON_DISPLAY_H * GROUP_ROLE_ICON_ASPECT)
const GROUP_ROLE_ICON_IMG_H = GROUP_ROLE_ICON_DISPLAY_H * 2
const GROUP_ROLE_ICON_IMG_W = Math.round(GROUP_ROLE_ICON_IMG_H * GROUP_ROLE_ICON_ASPECT)

function MemberRoleBadge({ role, t }: { role: string; t: (key: string) => string }) {
    const badge = resolveGroupRoleBadge(role)
    if (!badge) return null
    const isLeader = badge === 'leader'
    const label = isLeader ? t('familys.familyLeader') : t('familys.familyDeputyLeader')
    const src = isLeader ? GROUP_ROLE_ICON.leader : GROUP_ROLE_ICON.deputy

    return (
        <span
            tip={label}
            className={`inline-flex shrink-0 items-center ${tipBelowOnlyClass}`}
            aria-label={label}
        >
            <Image
                src={src}
                alt=""
                width={GROUP_ROLE_ICON_IMG_W}
                height={GROUP_ROLE_ICON_IMG_H}
                className="object-contain"
                style={{
                    width: GROUP_ROLE_ICON_DISPLAY_W,
                    height: GROUP_ROLE_ICON_DISPLAY_H,
                }}
                sizes={`${GROUP_ROLE_ICON_DISPLAY_W}px`}
            />
        </span>
    )
}

function FamilyBackFab({ label }: { label: string }) {
    return (
        <Link
            href="/group"
            className="fixed left-4 top-[calc(60px+12px)] z-40 inline-flex h-10 max-w-[calc(100vw-2rem)] items-center gap-2 rounded-full border border-white/25 bg-black/50 px-3.5 text-sm font-medium text-white shadow-[0_4px_20px_rgba(0,0,0,0.35)] backdrop-blur-md transition-colors hover:bg-black/65 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white/80 dark:border-white/15 dark:bg-black/60 dark:hover:bg-black/75 sm:left-6 sm:max-w-none md:left-8"
            aria-label={label}
        >
            <FiArrowLeft className="h-4 w-4 shrink-0" aria-hidden />
            <span className="truncate">{label}</span>
        </Link>
    )
}

function FamilyPageShell({
    sidebarOpen,
    onMenuClick,
    onSidebarClose,
    children,
}: {
    sidebarOpen: boolean
    onMenuClick: () => void
    onSidebarClose: () => void
    children: ReactNode
}) {
    return (
        <div className="min-h-screen bg-white text-black dark:bg-[#0c0d0e] dark:text-white">
            <Header onMenuClick={onMenuClick} />
            <div className="flex-1 min-h-screen w-full max-w-full overflow-x-hidden pt-[60px]">
                <div className="flex">
                    <Sidebar mode="drawer" isOpen={sidebarOpen} onClose={onSidebarClose} />
                    <div className="flex min-w-0 flex-1 flex-col">{children}</div>
                </div>
            </div>
            <BackToTop />
        </div>
    )
}

export default function FamilyDetailPageClient({
    groupId,
    initialData,
    currentUserId = null,
    canManageMembers = false,
}: FamilyDetailPageClientProps) {
    const { t } = useTranslation()
    const [sidebarOpen, setSidebarOpen] = useState(false)
    const [familyData, setFamilyData] = useState<FamilyData | null>(initialData)
    const [isLoading, setIsLoading] = useState(!initialData)
    const [viewerCard, setViewerCard] = useState<ViewerCardState | null>(null)
    const [viewerCardDepth, setViewerCardDepth] = useState<'root' | 'gift' | 'admin'>('root')
    const viewerCardRef = useRef<HTMLDivElement>(null)
    const confirmRef = useRef<HTMLDivElement>(null)
    const pendingMemberActionRef = useRef<{
        member: FamilyMember
        action: GroupMemberAction
    } | null>(null)
    const [confirmModalOpen, setConfirmModalOpen] = useState(false)
    const [confirmClosing, setConfirmClosing] = useState(false)
    const [confirmEntering, setConfirmEntering] = useState(false)
    const [confirmTitle, setConfirmTitle] = useState('')
    const [confirmMessage, setConfirmMessage] = useState('')
    const [confirmConfirmText, setConfirmConfirmText] = useState<string | undefined>(undefined)
    const [confirmSeverity, setConfirmSeverity] = useState<'info' | 'warning' | 'danger'>('warning')

    const openMemberViewerCard = useCallback((member: FamilyMember) => {
        const participant: ParticipantItem = {
            role: member.role,
            name: member.displayName,
            id: member.id,
            avatarUrl: member.avatar ?? undefined,
            profileApiKey: member.id,
        }
        setViewerCardDepth('root')
        setViewerCard((prev) => {
            if (prev?.user.id === member.id) return null
            return { mode: 'desktop', user: participant, top: 0, left: 0 }
        })
    }, [])

    const closeViewerCard = useCallback(() => {
        setViewerCard(null)
        setViewerCardDepth('root')
    }, [])

    const showApplyJoinButton = useMemo(() => {
        if (!familyData) return false
        if (!currentUserId) return true
        return !familyData.members.some((m) => m.id === currentUserId)
    }, [currentUserId, familyData])

    const reloadFamilyData = useCallback(async () => {
        if (!groupId) return
        try {
            const response = await fetch(`/api/group/${groupId}`)
            const result = await response.json()
            if (result.ok) {
                setFamilyData(result.data)
            }
        } catch {
            // ignore
        }
    }, [groupId])

    useEffect(() => {
        if (!initialData && groupId) {
            const fetchFamilyData = async () => {
                setIsLoading(true)
                try {
                    const response = await fetch(`/api/group/${groupId}`)
                    const result = await response.json()
                    if (result.ok) {
                        setFamilyData(result.data)
                    } else {
                        setFamilyData(null)
                    }
                } catch {
                    setFamilyData(null)
                } finally {
                    setIsLoading(false)
                }
            }
            fetchFamilyData()
        }
    }, [groupId, initialData])

    const closeMemberConfirm = useCallback(() => {
        setConfirmEntering(false)
        setConfirmClosing(true)
        window.setTimeout(() => {
            setConfirmModalOpen(false)
            setConfirmClosing(false)
            setConfirmTitle('')
            setConfirmMessage('')
            setConfirmConfirmText(undefined)
            setConfirmSeverity('warning')
            pendingMemberActionRef.current = null
        }, 200)
    }, [])

    const openMemberConfirm = useCallback(
        (
            member: FamilyMember,
            action: GroupMemberAction,
            title: string,
            message: string,
            confirmText: string,
            severity: 'warning' | 'danger'
        ) => {
            pendingMemberActionRef.current = { member, action }
            setConfirmTitle(title)
            setConfirmMessage(message)
            setConfirmConfirmText(confirmText)
            setConfirmSeverity(severity)
            setConfirmEntering(true)
            setConfirmModalOpen(true)
            setConfirmClosing(false)
            requestAnimationFrame(() => requestAnimationFrame(() => setConfirmEntering(false)))
        },
        []
    )

    const executeMemberAction = useCallback(
        async (member: FamilyMember, action: GroupMemberAction) => {
            try {
                const res = await fetch(
                    `/api/group/${encodeURIComponent(groupId)}/members/${encodeURIComponent(member.id)}`,
                    {
                        method: 'PATCH',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ action }),
                    }
                )
                const json = (await res.json()) as { ok?: boolean; message?: string }
                if (!res.ok || !json.ok) {
                    window.alert(json.message || t('familys.memberMenu.actionFailed'))
                    return
                }
                if (action === 'transfer_leader' && member.id !== currentUserId) {
                    window.location.reload()
                    return
                }
                await reloadFamilyData()
            } catch {
                window.alert(t('familys.memberMenu.actionFailed'))
            }
        },
        [groupId, t, reloadFamilyData, currentUserId]
    )

    const handleConfirmMemberAction = useCallback(async () => {
        const pending = pendingMemberActionRef.current
        if (!pending) {
            closeMemberConfirm()
            return
        }
        const { member, action } = pending
        pendingMemberActionRef.current = null
        closeMemberConfirm()
        await executeMemberAction(member, action)
    }, [closeMemberConfirm, executeMemberAction])

    const handleMemberAction = useCallback(
        async (member: FamilyMember, action: GroupMemberAction) => {
            const name = member.displayName
            const confirmByAction: Partial<
                Record<
                    GroupMemberAction,
                    {
                        title: string
                        message: string
                        confirmText: string
                        severity: 'warning' | 'danger'
                    }
                >
            > = {
                transfer_leader: {
                    title: t('familys.memberMenu.transferLeader'),
                    message: t('familys.memberMenu.confirmTransferLeader', { name }),
                    confirmText: t('familys.memberMenu.transferLeader'),
                    severity: 'warning',
                },
                demote_member: {
                    title: t('familys.memberMenu.demoteMember'),
                    message: t('familys.memberMenu.confirmDemoteMember', { name }),
                    confirmText: t('familys.memberMenu.demoteMember'),
                    severity: 'warning',
                },
                promote_deputy: {
                    title: t('familys.memberMenu.promoteDeputy'),
                    message: t('familys.memberMenu.confirmPromoteDeputy', { name }),
                    confirmText: t('familys.memberMenu.promoteDeputy'),
                    severity: 'warning',
                },
                kick: {
                    title: t('familys.memberMenu.kick'),
                    message: t('familys.memberMenu.confirmKick', { name }),
                    confirmText: t('familys.memberMenu.kick'),
                    severity: 'danger',
                },
            }
            const confirm = confirmByAction[action]
            if (confirm) {
                openMemberConfirm(
                    member,
                    action,
                    confirm.title,
                    confirm.message,
                    confirm.confirmText,
                    confirm.severity
                )
                return
            }
            await executeMemberAction(member, action)
        },
        [openMemberConfirm, executeMemberAction, t]
    )

    const coverUrl = useMemo(() => {
        if (!familyData) return DEFAULT_COVER
        const bannerResolved = resolveMediaUrl(familyData.banner)
        if (hasValidImageSrc(bannerResolved)) return bannerResolved
        return DEFAULT_COVER
    }, [familyData])

    if (isLoading) {
        return (
            <FamilyPageShell
                sidebarOpen={sidebarOpen}
                onMenuClick={() => setSidebarOpen(true)}
                onSidebarClose={() => setSidebarOpen(false)}
            >
                <main className="flex-1 min-w-0">
                    <FamilyBackFab label={t('familys.backToList')} />
                    <UserBannerSkeleton />
                    <div className="relative -mt-14 px-4 sm:-mt-[68px] sm:px-8 md:-mt-[80px] md:px-[120px]">
                        <div className="mx-auto max-w-[1600px]">
                            <div className="animate-pulse rounded-2xl border border-gray-200 bg-white/90 px-6 py-5 dark:border-white/10 dark:bg-[rgba(5,5,10,0.2)] sm:rounded-3xl">
                                <div className="flex gap-5">
                                    <div className="h-[88px] w-[88px] rounded-2xl bg-gray-200 dark:bg-neutral-800 sm:h-[104px] sm:w-[104px]" />
                                    <div className="flex-1 space-y-3 pt-2">
                                        <div className="h-7 w-48 rounded bg-gray-200 dark:bg-neutral-800" />
                                        <div className="h-4 w-24 rounded bg-gray-200 dark:bg-neutral-800" />
                                        <div className="flex gap-2">
                                            <div className="h-7 w-24 rounded-full bg-gray-200 dark:bg-neutral-800" />
                                            <div className="h-7 w-24 rounded-full bg-gray-200 dark:bg-neutral-800" />
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <section className="mt-10 px-4 pb-12 sm:px-8 md:px-[120px]">
                        <div className="mx-auto max-w-[1600px] space-y-8">
                            <div className="h-6 w-32 animate-pulse rounded bg-gray-200 dark:bg-neutral-800" />
                            <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
                                {Array.from({ length: 3 }).map((_, i) => (
                                    <div
                                        key={i}
                                        className="aspect-video animate-pulse rounded-xl bg-gray-200 dark:bg-neutral-800"
                                    />
                                ))}
                            </div>
                        </div>
                    </section>
                </main>
                <Footer />
            </FamilyPageShell>
        )
    }

    if (!familyData) {
        return (
            <FamilyPageShell
                sidebarOpen={sidebarOpen}
                onMenuClick={() => setSidebarOpen(true)}
                onSidebarClose={() => setSidebarOpen(false)}
            >
                <main className="flex flex-1 min-w-0 items-center justify-center px-4 py-20 sm:px-8 md:px-[120px]">
                    <div className="mx-auto max-w-md text-center">
                        <div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-gray-100 dark:bg-neutral-900">
                            <FiUsers className="h-8 w-8 text-gray-400 dark:text-gray-500" aria-hidden />
                        </div>
                        <h2 className="mb-2 text-xl font-semibold text-gray-900 dark:text-white sm:text-2xl">
                            {t('familys.notFound')}
                        </h2>
                        <p className="mb-6 text-sm text-gray-500 dark:text-gray-400">{t('familys.notFoundDesc')}</p>
                        <Link
                            href="/group"
                            className="inline-flex items-center gap-2 rounded-[12px] border border-gray-200 bg-white px-4 py-2.5 text-sm font-medium text-gray-700 shadow-sm transition-colors hover:bg-gray-50 dark:border-white/15 dark:bg-black/25 dark:text-gray-100 dark:hover:bg-white/10"
                        >
                            <FiArrowLeft className="h-4 w-4" aria-hidden />
                            {t('familys.backToList')}
                        </Link>
                    </div>
                </main>
                <Footer />
            </FamilyPageShell>
        )
    }

    const liveStreams: LiveStream[] = familyData.liveStreams.map((ls) => ({
        id: ls.roomId,
        streamerName: ls.displayName,
        title: ls.title,
        category: '',
        viewerCount: ls.viewers,
        thumbnail: ls.thumbnail || undefined,
        avatar: ls.avatar || undefined,
        startTime: String(ls.startedAt || ''),
        tags: [],
    }))

    return (
        <FamilyPageShell
            sidebarOpen={sidebarOpen}
            onMenuClick={() => setSidebarOpen(true)}
            onSidebarClose={() => setSidebarOpen(false)}
        >
            <main className="flex-1 min-w-0 overflow-visible">
                <FamilyBackFab label={t('familys.backToList')} />

                <section className="relative w-full overflow-visible">
                    <div
                        className="w-full min-h-[220px] bg-cover bg-center sm:min-h-[260px] md:min-h-[290px]"
                        style={{ backgroundImage: `url("${coverUrl}")` }}
                        role="img"
                        aria-label={familyData.name}
                    />
                    <div className="relative -mt-14 overflow-visible px-4 sm:-mt-[68px] sm:px-8 md:-mt-[80px] md:px-[120px]">
                        <div className="pointer-events-auto mx-auto max-w-[1600px] overflow-visible">
                            <div className="flex flex-col overflow-visible rounded-2xl border border-gray-200 bg-white/90 px-4 py-4 shadow-[0_18px_45px_rgba(0,0,0,0.18)] backdrop-blur dark:border-white/10 dark:bg-[rgba(5,5,10,0.2)] dark:shadow-[0_18px_45px_rgba(0,0,0,0.45)] sm:rounded-3xl sm:px-6 sm:py-5 md:px-8">
                                <div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:gap-6">
                                    <div className="-mt-10 shrink-0 sm:-mt-12 md:-mt-14">
                                        <GroupAvatar avatar={familyData.avatar} name={familyData.name} />
                                    </div>
                                    <div className="min-w-0 flex-1 pb-0.5 sm:pt-1 sm:pr-2">
                                        <h1 className="flex flex-wrap items-center gap-1.5 text-lg font-semibold text-gray-900 dark:text-white sm:text-xl md:text-2xl">
                                            <span className="truncate">{familyData.name}</span>
                                            {familyData.isVerified ? (
                                                <MdVerified
                                                    className="h-5 w-5 shrink-0 text-cyan-400"
                                                    title={t('catch.verified')}
                                                />
                                            ) : null}
                                        </h1>
                                        <p className="mt-0.5 text-sm text-gray-500 dark:text-white/70">#{familyData.id}</p>
                                        {familyData.description ? (
                                            <p className="mt-2 line-clamp-3 text-sm text-gray-600 dark:text-gray-300 sm:line-clamp-none sm:whitespace-pre-wrap">
                                                {familyData.description}
                                            </p>
                                        ) : null}
                                        <div className="mt-2.5 flex flex-wrap items-center gap-2">
                                            <span className="inline-flex items-center gap-1.5 rounded-full bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-700 dark:bg-neutral-800 dark:text-gray-200 sm:px-3 sm:py-1.5 sm:text-sm">
                                                <FiUsers className="h-3.5 w-3.5 shrink-0 opacity-70" aria-hidden />
                                                {t('familys.statsMembers', { value: formatViews(familyData.membersCount) })}
                                            </span>
                                            <span className="inline-flex items-center gap-1.5 rounded-full bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-700 dark:bg-neutral-800 dark:text-gray-200 sm:px-3 sm:py-1.5 sm:text-sm">
                                                <FiUser className="h-3.5 w-3.5 shrink-0 opacity-70" aria-hidden />
                                                {t('familys.statsArtists', { value: formatViews(familyData.artistsCount) })}
                                            </span>
                                            {liveStreams.length > 0 ? (
                                                <span className="inline-flex items-center rounded-full bg-emerald-500/15 px-2.5 py-1 text-xs font-medium text-emerald-700 ring-1 ring-emerald-500/30 dark:text-emerald-300 sm:px-3 sm:py-1.5 sm:text-sm">
                                                    {t('familys.statsLive', { value: liveStreams.length })}
                                                </span>
                                            ) : null}
                                        </div>
                                    </div>
                                </div>
                                <div className="mt-4 flex flex-wrap items-center justify-end gap-2 sm:mt-3">
                                    {showApplyJoinButton ? (
                                        <button
                                            type="button"
                                            tip={t('familys.applyJoin')}
                                            onClick={() => {
                                                window.alert(t('familys.actionComingSoon'))
                                            }}
                                            className={`inline-flex h-10 items-center gap-2 rounded-[12px] border border-gray-900 bg-gray-900 px-4 text-xs font-medium text-white shadow-sm transition-colors hover:bg-gray-800 active:bg-gray-950 dark:border-white dark:bg-white dark:text-gray-900 dark:hover:bg-gray-100 ${tipBelowOnlyClass}`}
                                        >
                                            <FiUserPlus className="h-4 w-4 shrink-0" aria-hidden />
                                            <span>{t('familys.applyJoin')}</span>
                                        </button>
                                    ) : null}
                                    <button
                                        type="button"
                                        tip={t('familys.report')}
                                        onClick={() => {
                                            window.alert(t('familys.actionComingSoon'))
                                        }}
                                        className={`inline-flex h-10 items-center gap-2 rounded-[12px] border border-gray-200 bg-white/90 px-4 text-xs font-medium text-gray-700 shadow-sm transition-colors hover:bg-gray-50 dark:border-white/15 dark:bg-black/25 dark:text-gray-100 dark:hover:bg-white/10 ${tipBelowOnlyClass}`}
                                    >
                                        <FiFlag className="h-4 w-4 shrink-0" aria-hidden />
                                        <span>{t('familys.report')}</span>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                </section>

                <section className="mt-8 px-4 pb-12 sm:mt-10 sm:px-8 md:mt-12 md:px-[120px]">
                    <div className="mx-auto max-w-[1600px]">
                        {liveStreams.length > 0 ? (
                            <div className="mb-10 sm:mb-12">
                                <h2 className="mb-4 text-base font-semibold text-gray-900 dark:text-white sm:text-lg">
                                    {t('familys.liveStreams')}
                                </h2>
                                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
                                    {liveStreams.map((stream) => (
                                        <LiveCard key={stream.id} stream={stream} t={t} />
                                    ))}
                                </div>
                            </div>
                        ) : null}

                        {familyData.members.length > 0 ? (
                            <div className="overflow-visible rounded-2xl border border-gray-200 bg-white shadow-sm dark:border-white/10 dark:bg-[#0c0d0e] dark:shadow-[0_8px_30px_rgba(0,0,0,0.25)]">
                                <div className="flex items-center justify-between gap-3 border-b border-gray-100 bg-gray-50/80 px-4 py-3.5 dark:border-white/10 dark:bg-white/[0.03] sm:px-5">
                                    <h2 className="flex items-center gap-2 text-base font-semibold text-gray-900 dark:text-white sm:text-lg">
                                        <FiUsers
                                            className="h-5 w-5 shrink-0 text-gray-500 dark:text-gray-400"
                                            aria-hidden
                                        />
                                        {t('familys.memberList')}
                                    </h2>
                                    <span className="shrink-0 rounded-full bg-white px-2.5 py-1 text-xs font-semibold tabular-nums text-gray-600 ring-1 ring-gray-200/80 dark:bg-neutral-800 dark:text-gray-300 dark:ring-white/10">
                                        {familyData.members.length}
                                    </span>
                                </div>
                                <div className="p-3 sm:p-4 md:p-5">
                                    <div className="grid grid-cols-1 gap-2 overflow-visible sm:grid-cols-2 sm:gap-3 xl:grid-cols-3">
                                        {familyData.members.map((member) => (
                                            <MemberCard
                                                key={member.id}
                                                member={member}
                                                t={t}
                                                onSelect={openMemberViewerCard}
                                                canManage={
                                                    canManageMembers && member.id !== currentUserId
                                                }
                                                onMemberAction={handleMemberAction}
                                            />
                                        ))}
                                    </div>
                                </div>
                            </div>
                        ) : null}

                        {familyData.members.length === 0 && liveStreams.length === 0 ? (
                            <div className="flex flex-col items-center justify-center rounded-xl border border-dashed border-gray-200 py-16 text-center dark:border-white/10">
                                <FiUsers className="mb-3 h-12 w-12 text-gray-300 dark:text-gray-600" aria-hidden />
                                <p className="text-sm text-gray-500 dark:text-gray-400">{t('familys.noMemberList')}</p>
                            </div>
                        ) : null}
                    </div>
                </section>
            </main>
            <Footer />
            {viewerCard ? (
                <ViewerCard
                    cardRef={viewerCardRef}
                    viewerCard={viewerCard}
                    viewerCardDepth={viewerCardDepth}
                    t={t}
                    onClose={closeViewerCard}
                    onBackToRoot={() => setViewerCardDepth('root')}
                    onGift={() => closeViewerCard()}
                    streamerId={undefined}
                />
            ) : null}
            <ConfirmModal
                confirmRef={confirmRef}
                isOpen={confirmModalOpen}
                title={confirmTitle}
                message={confirmMessage}
                confirmText={confirmConfirmText}
                onClose={closeMemberConfirm}
                onConfirm={handleConfirmMemberAction}
                confirmClosing={confirmClosing}
                confirmEntering={confirmEntering}
                severity={confirmSeverity}
            />
        </FamilyPageShell>
    )
}
