'use client'

import { useState, useEffect, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { FaChrome, FaFirefoxBrowser, FaSafari } from 'react-icons/fa'
import { SiMicrosoftedge } from 'react-icons/si'
import { FiGlobe } from 'react-icons/fi'

// components
import Header from '@/components/Header'
import Sidebar from '@/components/Sidebar'
import Footer from '@/components/Footer'

// _components
import ProfileSidebar from '../_components/ProfileSidebar'
import { NotificationsPageSkeleton } from '../_components/Skeletons'

// contexts
import { useToast } from '@/contexts/ToastContext'

// lib
import {
    DESKTOP_NOTIFICATION_SETTING_ID,
    getDefaultNotificationSettings,
    type NotificationSettingItem,
} from '@/lib/notifications/notificationSettingCatalog'
import { writeNotificationSettingsCache } from '@/lib/notifications/notificationSettingsCache'

type NotificationSetting = NotificationSettingItem & {
    pushDisabled?: boolean
}

export default function NotificationsPageClient() {
    // Translations
    const { t } = useTranslation()
    const { showToast } = useToast()

    // States
    const [sidebarOpen, setSidebarOpen] = useState(false)
    const [desktopNotificationEnabled, setDesktopNotificationEnabled] = useState(false)
    const [settings, setSettings] = useState<NotificationSetting[]>([])
    const [hasChanges, setHasChanges] = useState(false)
    const [loading, setLoading] = useState(true)
    const [browserPushAllowed, setBrowserPushAllowed] = useState(false)

    const canUseDesktopPush =
        desktopNotificationEnabled &&
        browserPushAllowed &&
        typeof window !== 'undefined' &&
        'Notification' in window

    const applyPushDisabled = (list: NotificationSettingItem[]): NotificationSetting[] =>
        list.map((item) => ({
            ...item,
            pushDisabled: !canUseDesktopPush,
        }))

    const getBrowserIcon = () => {
        if (typeof navigator === 'undefined') {
            return <FiGlobe className="w-4 h-4" />
        }
        const ua = navigator.userAgent
        switch (true) {
            case ua.includes('Edg/'):
                return <SiMicrosoftedge className="w-4 h-4" />
            case ua.includes('Firefox/'):
                return <FaFirefoxBrowser className="w-4 h-4" />
            case ua.includes('Chrome/'):
                return <FaChrome className="w-4 h-4" />
            case ua.includes('Safari/'):
                return <FaSafari className="w-4 h-4" />
            default:
                return <FiGlobe className="w-4 h-4" />
        }
    }

    const fetchSettings = useCallback(async () => {
        setLoading(true)
        try {
            const response = await fetch('/api/profile/notifications')
            const data = await response.json()
            if (data.ok) {
                const notificationSettings = (data.settings ?? []).filter(
                    (s: NotificationSetting) => s.id !== DESKTOP_NOTIFICATION_SETTING_ID
                ) as NotificationSettingItem[]
                const list =
                    notificationSettings.length > 0
                        ? notificationSettings
                        : getDefaultNotificationSettings()
                setSettings(applyPushDisabled(list))
                if (typeof data.desktopNotificationEnabled === 'boolean') {
                    setDesktopNotificationEnabled(data.desktopNotificationEnabled)
                } else {
                    const desktopSetting = (data.settings ?? []).find(
                        (s: NotificationSetting) => s.id === DESKTOP_NOTIFICATION_SETTING_ID
                    )
                    if (desktopSetting) {
                        setDesktopNotificationEnabled(desktopSetting.pushEnabled)
                    }
                }
                writeNotificationSettingsCache({
                    desktopNotificationEnabled:
                        typeof data.desktopNotificationEnabled === 'boolean'
                            ? data.desktopNotificationEnabled
                            : Boolean(
                                  (data.settings ?? []).find(
                                      (s: NotificationSetting) =>
                                          s.id === DESKTOP_NOTIFICATION_SETTING_ID
                                  )?.pushEnabled
                              ),
                    settings: list,
                })
            } else {
                setSettings(applyPushDisabled(getDefaultNotificationSettings()))
            }
        } catch (error) {
            console.error('Failed to fetch notification settings:', error)
            setSettings(applyPushDisabled(getDefaultNotificationSettings()))
        } finally {
            setLoading(false)
        }
    }, [])

    useEffect(() => {
        if (typeof window === 'undefined' || !('Notification' in window)) {
            setBrowserPushAllowed(false)
            return
        }
        setBrowserPushAllowed(Notification.permission === 'granted')
    }, [])

    useEffect(() => {
        void fetchSettings()
    }, [fetchSettings])

    useEffect(() => {
        setSettings((prev) =>
            prev.map((item) => ({
                ...item,
                pushDisabled: !canUseDesktopPush,
            }))
        )
    }, [canUseDesktopPush])

    const handleSettingChange = (id: string, type: 'push' | 'record', value: boolean) => {
        setSettings((prev) =>
            prev.map((setting) =>
                setting.id === id
                    ? { ...setting, [type === 'push' ? 'pushEnabled' : 'recordEnabled']: value }
                    : setting
            )
        )
        setHasChanges(true)
    }

    const handleReset = () => {
        setSettings(applyPushDisabled(getDefaultNotificationSettings()))
        setDesktopNotificationEnabled(false)
        setHasChanges(true)
    }

    const handleSave = async () => {
        try {
            const response = await fetch('/api/profile/notifications', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ settings, desktopNotificationEnabled }),
            })
            const data = await response.json()
            if (data.ok) {
                setHasChanges(false)
                writeNotificationSettingsCache({
                    desktopNotificationEnabled,
                    settings: settings.map(({ id, pushEnabled, recordEnabled }) => ({
                        id,
                        pushEnabled,
                        recordEnabled,
                    })),
                })
                showToast(t('profile.notifications.saveSuccess'), 'success')
            } else {
                showToast(data.message || t('common.error'), 'error')
            }
        } catch (error) {
            console.error('Failed to save notification settings:', error)
            showToast(t('common.error'), 'error')
        }
    }

    const handleDesktopNotificationToggle = async (enabled: boolean) => {
        setHasChanges(true)
        if (enabled) {
            if ('Notification' in window) {
                const permission = await Notification.requestPermission()
                const granted = permission === 'granted'
                setBrowserPushAllowed(granted)
                setDesktopNotificationEnabled(granted)
                if (!granted) {
                    showToast(t('profile.notifications.permissionDenied'), 'error')
                }
                return
            }
            setDesktopNotificationEnabled(false)
            return
        }
        setDesktopNotificationEnabled(false)
    }

    if (loading) {
        return (
            <div className="min-h-screen supports-[height:100svh]:min-h-[100svh] bg-white dark:bg-[#0c0d0e] text-gray-900 dark:text-white flex flex-col">
                <Header onMenuClick={() => setSidebarOpen(true)} />
                <Sidebar isOpen={sidebarOpen} onClose={() => setSidebarOpen(false)} mode="drawer" />
                <NotificationsPageSkeleton />
                <Footer />
            </div>
        )
    }

    return (
        <div className="min-h-screen supports-[height:100svh]:min-h-[100svh] bg-white dark:bg-[#0c0d0e] text-gray-900 dark:text-white flex flex-col">
            <Header onMenuClick={() => setSidebarOpen(true)} />
            <Sidebar isOpen={sidebarOpen} onClose={() => setSidebarOpen(false)} mode="drawer" />

            <div className="flex-1 w-full max-w-[960px] mx-auto px-4 pt-[6rem] md:pt-[6rem] pb-10">
                <ProfileSidebar />

                <div className="mt-8">
                    <h2 className="text-2xl font-semibold mb-6">{t('profile.notifications.title')}</h2>

                    <div className="mb-9">
                        <h3 className="text-lg font-semibold mb-2">{t('profile.notifications.desktop.title')}</h3>
                        <ul className="text-xs text-gray-600 dark:text-gray-400 space-y-1 mb-5">
                            <li>{t('profile.notifications.desktop.desc1')}</li>
                            <li>{t('profile.notifications.desktop.desc2')}</li>
                            <li>{t('profile.notifications.desktop.desc3')}</li>
                        </ul>

                        <div className="border border-gray-300 dark:border-gray-600 rounded">
                            <dl className="flex items-center justify-between h-12 px-5">
                                <dt className="flex items-center text-sm font-semibold">
                                    <span className="w-8 h-8 mr-2 bg-blue-500 rounded flex items-center justify-center text-white text-xs">
                                        {getBrowserIcon()}
                                    </span>
                                    {t('profile.notifications.desktop.browserNotification')}
                                </dt>
                                <dd>
                                    <label className="relative inline-block w-9 h-5 cursor-pointer">
                                        <input
                                            type="checkbox"
                                            checked={desktopNotificationEnabled}
                                            onChange={(e) => handleDesktopNotificationToggle(e.target.checked)}
                                            className="sr-only"
                                        />
                                        <span
                                            className={`absolute inset-0 rounded-full transition-colors ${desktopNotificationEnabled
                                                ? 'bg-blue-500'
                                                : 'bg-gray-300 dark:bg-gray-600'
                                                }`}
                                        >
                                            <span
                                                className={`absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full transition-transform ${desktopNotificationEnabled ? 'translate-x-4' : ''
                                                    }`}
                                            />
                                        </span>
                                    </label>
                                </dd>
                            </dl>
                        </div>
                    </div>

                    <div>
                        <div className="flex items-center justify-between mb-5">
                            <div>
                                <h3 className="text-lg font-semibold mb-2">{t('profile.notifications.content.title')}</h3>
                                <ul className="text-xs text-gray-600 dark:text-gray-400 space-y-1">
                                    <li>{t('profile.notifications.content.desc1')}</li>
                                    <li>{t('profile.notifications.content.desc2')}</li>
                                </ul>
                            </div>
                            <div className="flex gap-2">
                                <button
                                    onClick={handleReset}
                                    className="px-4 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
                                >
                                    {t('profile.notifications.content.reset')}
                                </button>
                                <button
                                    onClick={handleSave}
                                    disabled={!hasChanges}
                                    className={`px-4 py-2 text-sm rounded transition-colors ${hasChanges
                                        ? 'bg-blue-500 text-white hover:bg-blue-600'
                                        : 'bg-gray-200 dark:bg-gray-700 text-gray-400 cursor-not-allowed'
                                        }`}
                                >
                                    {t('profile.notifications.content.save')}
                                </button>
                            </div>
                        </div>

                        <div className="space-y-8 pt-10 border-t border-gray-300 dark:border-gray-600">
                            <div className="relative pl-28">
                                <h4 className="absolute left-0 top-0 w-24 text-sm font-semibold">{t('profile.notifications.sections.favorites')}</h4>
                                <div className="flex items-center justify-end mb-4">
                                    <div className="flex gap-5 text-xs text-gray-600 dark:text-gray-400">
                                        <span className="opacity-30">{t('profile.notifications.content.pushSetting')}</span>
                                        <span>{t('profile.notifications.content.recordSetting')}</span>
                                    </div>
                                </div>
                                <div className="space-y-4">
                                    {settings
                                        .filter((s) => s.id.startsWith('favorite_'))
                                        .map((setting) => (
                                            <NotificationItem
                                                key={setting.id}
                                                setting={setting}
                                                onChange={handleSettingChange}
                                            />
                                        ))}
                                </div>
                            </div>

                            <div className="relative pl-28 border-t border-gray-300 dark:border-gray-600 pt-8">
                                <h4 className="absolute left-0 top-8 w-24 text-sm font-semibold">{t('profile.notifications.sections.myActivity')}</h4>
                                <div className="flex items-center justify-end mb-4">
                                    <div className="flex gap-5 text-xs text-gray-600 dark:text-gray-400">
                                        <span className="opacity-30">{t('profile.notifications.content.pushSetting')}</span>
                                        <span>{t('profile.notifications.content.recordSetting')}</span>
                                    </div>
                                </div>
                                <div className="space-y-4">
                                    {settings
                                        .filter((s) => ['comment_mention', 'reply_mention', 'content_like', 'note_received'].includes(s.id))
                                        .map((setting) => (
                                            <NotificationItem
                                                key={setting.id}
                                                setting={setting}
                                                onChange={handleSettingChange}
                                            />
                                        ))}
                                </div>
                            </div>

                            <div className="relative pl-28 border-t border-gray-300 dark:border-gray-600 pt-8">
                                <h4 className="absolute left-0 top-8 w-24 text-sm font-semibold">{t('profile.notifications.sections.myStation')}</h4>
                                <div className="flex items-center justify-end mb-4">
                                    <div className="flex gap-5 text-xs text-gray-600 dark:text-gray-400">
                                        <span className="opacity-30">{t('profile.notifications.content.pushSetting')}</span>
                                        <span>{t('profile.notifications.content.recordSetting')}</span>
                                    </div>
                                </div>
                                <div className="space-y-4">
                                    {settings
                                        .filter((s) => s.id.startsWith('my_station_'))
                                        .map((setting) => (
                                            <NotificationItem
                                                key={setting.id}
                                                setting={setting}
                                                onChange={handleSettingChange}
                                            />
                                        ))}
                                </div>
                            </div>

                            <div className="relative pl-28 border-t border-gray-300 dark:border-gray-600 pt-8">
                                <h4 className="absolute left-0 top-8 w-24 text-sm font-semibold">{t('profile.notifications.sections.gifts')}</h4>
                                <div className="flex items-center justify-end mb-4">
                                    <div className="flex gap-5 text-xs text-gray-600 dark:text-gray-400">
                                        <span className="opacity-30">{t('profile.notifications.content.pushSetting')}</span>
                                        <span>{t('profile.notifications.content.recordSetting')}</span>
                                    </div>
                                </div>
                                <div className="space-y-4">
                                    {settings
                                        .filter((s) => ['sticker_gift', 'ad_balloon', 'subscription_start'].includes(s.id))
                                        .map((setting) => (
                                            <NotificationItem
                                                key={setting.id}
                                                setting={setting}
                                                onChange={handleSettingChange}
                                            />
                                        ))}
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <Footer />
        </div>
    )
}

function NotificationItem({
    setting,
    onChange,
}: {
    setting: NotificationSetting
    onChange: (id: string, type: 'push' | 'record', value: boolean) => void
}) {
    const { t } = useTranslation()
    const settingKey = `profile.notifications.items.${setting.id}`

    return (
        <div className="flex items-start justify-between">
            <div className="flex-1">
                <p className="text-sm font-medium">{t(`${settingKey}.title`)}</p>
                <span className="text-xs text-gray-600 dark:text-gray-400 mt-1 block">
                    {t(`${settingKey}.desc`)}
                </span>
            </div>
            <div className="flex items-center gap-5 pt-2">
                <label className="relative inline-block w-9 h-5 cursor-pointer">
                    <input
                        type="checkbox"
                        checked={setting.pushEnabled}
                        onChange={(e) => onChange(setting.id, 'push', e.target.checked)}
                        disabled={setting.pushDisabled}
                        className="sr-only"
                    />
                    <span
                        className={`absolute inset-0 rounded-full transition-colors ${setting.pushEnabled
                            ? 'bg-blue-500'
                            : 'bg-gray-300 dark:bg-gray-600'
                            } ${setting.pushDisabled ? 'opacity-30 cursor-not-allowed' : ''}`}
                    >
                        <span
                            className={`absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full transition-transform ${setting.pushEnabled ? 'translate-x-4' : ''
                                }`}
                        />
                    </span>
                </label>
                <label className="relative inline-block w-9 h-5 cursor-pointer">
                    <input
                        type="checkbox"
                        checked={setting.recordEnabled}
                        onChange={(e) => onChange(setting.id, 'record', e.target.checked)}
                        className="sr-only"
                    />
                    <span
                        className={`absolute inset-0 rounded-full transition-colors ${setting.recordEnabled
                            ? 'bg-blue-500'
                            : 'bg-gray-300 dark:bg-gray-600'
                            }`}
                    >
                        <span
                            className={`absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full transition-transform ${setting.recordEnabled ? 'translate-x-4' : ''
                                }`}
                        />
                    </span>
                </label>
            </div>
        </div>
    )
}
