'use client'

import { useState, useRef, useEffect, useCallback } from 'react'
import { FiChevronRight } from 'react-icons/fi'
import { useTranslation } from 'react-i18next'
import { formatDateTime } from '@/utils/formatDate'
import { resolveGroupNotificationText } from '@/lib/notifications/resolveGroupNotificationText'
import type { UserNotificationWsPayload } from '@/lib/notifications/userNotificationTypes'
import { useUserNotifications } from '@/contexts/UserNotificationsContext'
import { useNoticeWs } from '@/contexts/NoticeWsContext'
import { clearOptimisticUnread } from '@/lib/notifications/unreadBadge'
import {
    dispatchUserNotificationsUpdated,
    USER_NOTIFICATIONS_LIST_EVENT,
    USER_NOTIFICATIONS_UPDATED_EVENT,
    type UserNotificationListItem,
    type UserNotificationsListDetail,
    type UserNotificationsUpdatedDetail,
} from '@/lib/notices/wsNotice'
import type { TFunction } from 'i18next'

interface Notice {
    id: string
    title: string
    date: string
    url: string
}

interface Notification {
    id: string
    type: string
    title: string
    content: string
    url: string | null
    isRead: boolean
    date: string
}

interface NotificationPanelProps {
    isOpen: boolean
    onClose: () => void
    triggerRef?: React.RefObject<HTMLElement | null>
}

function listItemToNotification(item: UserNotificationListItem): Notification {
    return {
        id: item.id,
        type: item.type,
        title: item.title,
        content: item.content,
        url: item.url,
        isRead: item.isRead,
        date: item.date,
    }
}

function wsPayloadToNotification(payload: UserNotificationWsPayload, t: TFunction): Notification {
    const resolved = resolveGroupNotificationText(t, payload.type, payload.content, payload.params)
    return {
        id: payload.id,
        type: payload.type,
        title: resolved?.title || payload.title,
        content: resolved?.content || payload.content,
        url: payload.url,
        isRead: Boolean(payload.isRead),
        date: new Date((payload.createdAt || 0) * 1000).toISOString(),
    }
}

export default function NotificationPanel({ isOpen, onClose, triggerRef }: NotificationPanelProps) {
    const { t } = useTranslation()
    const { hasUnread, refreshUnread } = useUserNotifications()
    const { listNotifications, deleteNotification, wsReady } = useNoticeWs()

    const [activeTab, setActiveTab] = useState<'notification' | 'notice'>('notice')
    const [notifications, setNotifications] = useState<Notification[]>([])
    const [notices, setNotices] = useState<Notice[]>([])
    const [loading, setLoading] = useState(false)
    const [loadingNotices, setLoadingNotices] = useState(false)

    const panelRef = useRef<HTMLDivElement>(null)

    const fetchNotifications = useCallback(async () => {
        if (!wsReady) {
            setNotifications([])
            return
        }
        setLoading(true)
        try {
            const list = await listNotifications()
            setNotifications(list.map(listItemToNotification))
        } catch (error) {
            console.error('Failed to fetch notifications:', error)
        } finally {
            setLoading(false)
        }
    }, [listNotifications, wsReady])

    useEffect(() => {
        if (!isOpen) return
        void fetchNotifications()
        if (activeTab === 'notice') {
            void fetchNotices()
        }
    }, [isOpen, activeTab, fetchNotifications])

    useEffect(() => {
        if (isOpen && hasUnread) {
            setActiveTab('notification')
        }
    }, [isOpen, hasUnread])

    useEffect(() => {
        const onList = (event: Event) => {
            const detail = (event as CustomEvent<UserNotificationsListDetail>).detail
            const list = detail?.notifications ?? []
            setNotifications(list.map(listItemToNotification))
        }
        window.addEventListener(USER_NOTIFICATIONS_LIST_EVENT, onList)
        return () => window.removeEventListener(USER_NOTIFICATIONS_LIST_EVENT, onList)
    }, [])

    useEffect(() => {
        const onUpdated = (event: Event) => {
            const detail = (event as CustomEvent<UserNotificationsUpdatedDetail>).detail
            const payload = detail?.payload
            if (payload) {
                const item = wsPayloadToNotification(payload, t)
                setNotifications((prev) => {
                    if (prev.some((n) => n.id === item.id)) return prev
                    return [item, ...prev]
                })
            }
            if (isOpen) {
                void fetchNotifications()
            }
        }
        window.addEventListener(USER_NOTIFICATIONS_UPDATED_EVENT, onUpdated)
        return () => window.removeEventListener(USER_NOTIFICATIONS_UPDATED_EVENT, onUpdated)
    }, [isOpen, t, fetchNotifications])

    const fetchNotices = async () => {
        setLoadingNotices(true)
        try {
            const response = await fetch('/api/notices')
            const data = await response.json()
            if (data.ok) {
                setNotices(data.notices || [])
            }
        } catch (error) {
            console.error('Failed to fetch notices:', error)
        } finally {
            setLoadingNotices(false)
        }
    }

    const handleNotificationClick = async (notification: Notification) => {
        try {
            const ok = await deleteNotification(notification.id)
            if (ok) {
                setNotifications((prev) => prev.filter((n) => n.id !== notification.id))
                dispatchUserNotificationsUpdated()
                clearOptimisticUnread()
                void refreshUnread()
            }
        } catch (error) {
            console.error('Failed to delete notification:', error)
        }
        if (notification.url) {
            window.location.href = notification.url
        }
    }

    useEffect(() => {
        const handleClickOutside = (event: MouseEvent) => {
            const target = event.target as Node
            if (!panelRef.current) return
            if (panelRef.current.contains(target)) return
            if (triggerRef?.current?.contains(target)) return
            onClose()
        }

        if (isOpen) {
            document.addEventListener('mousedown', handleClickOutside)
        }

        return () => {
            document.removeEventListener('mousedown', handleClickOutside)
        }
    }, [isOpen, onClose, triggerRef])

    if (!isOpen) return null

    return (
        <div
            ref={panelRef}
            className="fixed left-4 right-4 top-14 w-auto z-[120] md:absolute md:left-auto md:right-0 md:top-full md:mt-2 md:w-[404px] md:max-w-[90vw] bg-white dark:bg-[#1C1E22] border border-gray-200/20 dark:border-gray-700/30 rounded-xl shadow-lg pt-8"
        >
            <div className="flex items-start relative w-full h-10 px-4 md:px-8 after:content-[''] after:absolute after:left-1/2 after:bottom-0 after:bg-gray-200/20 dark:after:bg-gray-700/30 after:w-[calc(100%-64px)] after:h-px after:-translate-x-1/2">
                <div className="mr-3">
                    <h2 className="m-0">
                        <button
                            type="button"
                            onClick={() => setActiveTab('notification')}
                            className={`flex items-center justify-center relative h-10 px-6 border-b-2 font-normal text-center bg-transparent border-0 cursor-pointer ${activeTab === 'notification'
                                ? 'border-[#0182FF] font-semibold'
                                : 'border-transparent'
                                }`}
                        >
                            <span className={`relative text-base ${activeTab === 'notification'
                                ? 'text-[#0182FF] font-semibold'
                                : 'text-[#525661] dark:text-[#D5D7DC]'
                                }`}>
                                {t('notificationPanel.tab.notification')}
                            </span>
                        </button>
                    </h2>
                </div>
                <div>
                    <h2 className="m-0">
                        <button
                            type="button"
                            onClick={() => setActiveTab('notice')}
                            className={`flex items-center justify-center relative h-10 px-6 border-b-2 font-normal text-center bg-transparent border-0 cursor-pointer ${activeTab === 'notice'
                                ? 'border-[#0182FF] font-semibold'
                                : 'border-transparent'
                                }`}
                        >
                            <span className={`relative text-base ${activeTab === 'notice'
                                ? 'text-[#0182FF] font-semibold'
                                : 'text-[#525661] dark:text-[#D5D7DC]'
                                }`}>
                                {t('notificationPanel.tab.notice')}
                            </span>
                        </button>
                    </h2>
                </div>
                {activeTab === 'notice' && (
                    <a
                        href="/notices"
                        rel="noopener noreferrer"
                        className="absolute right-4 md:right-8"
                    >
                        <button className="w-6 h-6 bg-transparent border-0 cursor-pointer text-[0] leading-[0]">
                            <FiChevronRight className="w-6 h-6 text-[#525661] dark:text-[#D5D7DC]" />
                        </button>
                    </a>
                )}
            </div>

            {activeTab === 'notice' && (
                <div className="pt-2.5">
                    <div className="relative overflow-y-auto overscroll-contain h-[calc(100vh-405px)] md:h-[405px] py-0 px-4 md:px-8">
                        {loadingNotices ? (
                            <div className="flex items-center justify-center h-full">
                                <p className="text-[#757B8A] dark:text-[#9196A1] text-sm m-0">
                                    {t('notificationPanel.loading')}
                                </p>
                            </div>
                        ) : notices.length === 0 ? (
                            <div className="flex items-center justify-center h-full">
                                <div className="text-center">
                                    <p className="text-[#757B8A] dark:text-[#9196A1] text-sm m-0">
                                        {t('notificationPanel.emptyNotices')}
                                    </p>
                                </div>
                            </div>
                        ) : (
                            <ul className="list-none p-0 m-0">
                                {notices.map((notice, index) => (
                                    <li
                                        key={notice.id}
                                        className={index !== notices.length - 1 ? 'mb-1' : ''}
                                    >
                                        <a
                                            href={notice.url}
                                            target="_blank"
                                            rel="noopener noreferrer"
                                            className="block p-3 rounded-lg transition-colors hover:bg-gray-100 dark:hover:bg-[#3B3D45] group no-underline"
                                        >
                                            <p className="text-[#525661] dark:text-[#D5D7DC] text-sm leading-[1.4] m-0 group-hover:text-[#17191C] dark:group-hover:text-[#E2E4E9] group-hover:font-medium">
                                                {notice.title}
                                            </p>
                                            <span className="block mt-1 text-[#ACB0B9] dark:text-[#757B8A] text-xs">
                                                {formatDateTime(notice.date)}
                                            </span>
                                        </a>
                                    </li>
                                ))}
                            </ul>
                        )}
                    </div>
                </div>
            )}

            {activeTab === 'notification' && (
                <div className="pt-2.5">
                    <div className="relative overflow-y-auto overscroll-contain h-[calc(100vh-405px)] md:h-[405px] py-0 px-4 md:px-8">
                        {loading ? (
                            <div className="flex items-center justify-center h-full">
                                <p className="text-[#757B8A] dark:text-[#9196A1] text-sm m-0">
                                    {t('notificationPanel.loading')}
                                </p>
                            </div>
                        ) : !wsReady ? (
                            <div className="flex items-center justify-center h-full">
                                <p className="text-[#757B8A] dark:text-[#9196A1] text-sm m-0">
                                    {t('notificationPanel.loading')}
                                </p>
                            </div>
                        ) : notifications.length === 0 ? (
                            <div className="flex items-center justify-center h-full">
                                <div className="text-center">
                                    <p className="text-[#757B8A] dark:text-[#9196A1] text-sm m-0">
                                        {t('notificationPanel.emptyNotifications')}
                                    </p>
                                </div>
                            </div>
                        ) : (
                            <ul className="list-none p-0 m-0">
                                {notifications.map((notification, index) => {
                                    const resolved = resolveGroupNotificationText(
                                        t,
                                        notification.type,
                                        notification.content
                                    )
                                    const displayTitle = resolved?.title || notification.title
                                    const displayContent = resolved?.content || notification.content

                                    return (
                                    <li
                                        key={notification.id}
                                        className={index !== notifications.length - 1 ? 'mb-1' : ''}
                                    >
                                        <button
                                            type="button"
                                            onClick={() => void handleNotificationClick(notification)}
                                            className={`w-full text-left p-3 rounded-lg transition-colors hover:bg-gray-100 dark:hover:bg-[#3B3D45] group no-underline border-0 bg-transparent cursor-pointer ${!notification.isRead ? 'bg-blue-50 dark:bg-blue-900/20' : ''
                                                }`}
                                        >
                                            <div className="flex items-start gap-2">
                                                {!notification.isRead && (
                                                    <span className="w-2 h-2 bg-[#0182FF] rounded-full mt-1.5 flex-shrink-0" />
                                                )}
                                                <div className="flex-1 min-w-0">
                                                    <p className={`text-sm leading-[1.4] m-0 group-hover:text-[#17191C] dark:group-hover:text-[#E2E4E9] ${!notification.isRead
                                                        ? 'text-[#17191C] dark:text-[#E2E4E9] font-medium'
                                                        : 'text-[#525661] dark:text-[#D5D7DC]'
                                                        }`}>
                                                        {displayTitle}
                                                    </p>
                                                    {displayContent && (
                                                        <p className="text-[#ACB0B9] dark:text-[#757B8A] text-xs mt-1 m-0 line-clamp-2">
                                                            {displayContent}
                                                        </p>
                                                    )}
                                                    <span className="block mt-1 text-[#ACB0B9] dark:text-[#757B8A] text-xs">
                                                        {formatDateTime(notification.date)}
                                                    </span>
                                                </div>
                                            </div>
                                        </button>
                                    </li>
                                    )
                                })}
                            </ul>
                        )}
                    </div>
                </div>
            )}
        </div>
    )
}
