import AboutInfoDialog from '@/components/AboutInfoDialog'
import Donation from '@/components/Donation'
import Emoji from '@/components/Emoji'
import EmojiPackList from '@/components/EmojiPackList'
import EmojiPickerDialog from '@/components/EmojiPickerDialog'
import FavoriteRelaysSetting from '@/components/FavoriteRelaysSetting'
import MailboxSetting from '@/components/MailboxSetting'
import NoteList from '@/components/NoteList'
import Tabs from '@/components/Tabs'
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger
} from '@/components/ui/accordion'
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger
} from '@/components/ui/alert-dialog'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { Switch } from '@/components/ui/switch'
import { Tabs as RadixTabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import {
  BIG_RELAY_URLS,
  DEFAULT_FAVICON_URL_TEMPLATE,
  MEDIA_AUTO_LOAD_POLICY,
  NSFW_DISPLAY_POLICY,
  PRIMARY_COLORS,
  TPrimaryColor
} from '@/constants'
import { LocalizedLanguageNames, TLanguage } from '@/i18n'
import { cn, isSupportCheckConnectionType } from '@/lib/utils'
import MediaUploadServiceSetting from '@/pages/secondary/PostSettingsPage/MediaUploadServiceSetting'
import DefaultZapAmountInput from '@/pages/secondary/WalletPage/DefaultZapAmountInput'
import DefaultZapCommentInput from '@/pages/secondary/WalletPage/DefaultZapCommentInput'
import LightningAddressInput from '@/pages/secondary/WalletPage/LightningAddressInput'
import QuickZapSwitch from '@/pages/secondary/WalletPage/QuickZapSwitch'
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { useTheme } from '@/providers/ThemeProvider'
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useZap } from '@/providers/ZapProvider'
import storage, { dispatchSettingsChanged } from '@/services/local-storage.service'
import { TMediaAutoLoadPolicy, TNsfwDisplayPolicy } from '@/types'
import { disconnect, launchModal } from '@getalby/bitcoin-connect-react'
import {
  Check,
  Cog,
  Columns2,
  Copy,
  Info,
  KeyRound,
  LayoutList,
  List,
  Monitor,
  Moon,
  Palette,
  PanelLeft,
  PencilLine,
  RotateCcw,
  Server,
  Settings2,
  Smile,
  Sun,
  Wallet
} from 'lucide-react'
import { kinds } from 'nostr-tools'
import { forwardRef, HTMLProps, useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'

type TEmojiTab = 'my-packs' | 'explore'

const THEMES = [
  { key: 'system', label: 'System', icon: <Monitor className="size-5" /> },
  { key: 'light', label: 'Light', icon: <Sun className="size-5" /> },
  { key: 'dark', label: 'Dark', icon: <Moon className="size-5" /> },
  { key: 'pure-black', label: 'Pure Black', icon: <Moon className="size-5 fill-current" /> }
] as const

const LAYOUTS = [
  { key: false, label: 'Two-column', icon: <Columns2 className="size-5" /> },
  { key: true, label: 'Single-column', icon: <PanelLeft className="size-5" /> }
] as const

const NOTIFICATION_STYLES = [
  { key: 'detailed', label: 'Detailed', icon: <LayoutList className="size-5" /> },
  { key: 'compact', label: 'Compact', icon: <List className="size-5" /> }
] as const

export default function Settings() {
  const { t, i18n } = useTranslation()
  const { pubkey, nsec, ncryptsec } = useNostr()
  const { isSmallScreen } = useScreenSize()
  const [copiedNsec, setCopiedNsec] = useState(false)
  const [copiedNcryptsec, setCopiedNcryptsec] = useState(false)
  const [openSection, setOpenSection] = useState<string>('')

  // General settings
  const [language, setLanguage] = useState<TLanguage>(i18n.language as TLanguage)
  const {
    autoplay,
    setAutoplay,
    nsfwDisplayPolicy,
    setNsfwDisplayPolicy,
    hideContentMentioningMutedUsers,
    setHideContentMentioningMutedUsers,
    mediaAutoLoadPolicy,
    setMediaAutoLoadPolicy,
    faviconUrlTemplate,
    setFaviconUrlTemplate
  } = useContentPolicy()
  const {
    hideUntrustedNotes,
    updateHideUntrustedNotes,
    hideUntrustedInteractions,
    updateHideUntrustedInteractions,
    hideUntrustedNotifications,
    updateHideUntrustedNotifications
  } = useUserTrust()
  const {
    quickReaction,
    updateQuickReaction,
    quickReactionEmoji,
    updateQuickReactionEmoji,
    enableSingleColumnLayout,
    updateEnableSingleColumnLayout,
    notificationListStyle,
    updateNotificationListStyle
  } = useUserPreferences()

  // Appearance settings
  const { themeSetting, setThemeSetting, primaryColor, setPrimaryColor } = useTheme()

  // Wallet settings
  const { isWalletConnected, walletInfo } = useZap()

  // Relay settings
  const [relayTabValue, setRelayTabValue] = useState('favorite-relays')

  // Emoji settings
  const [emojiTab, setEmojiTab] = useState<TEmojiTab>('my-packs')

  // System settings
  const [filterOutOnionRelays, setFilterOutOnionRelays] = useState(storage.getFilterOutOnionRelays())

  const handleLanguageChange = (value: TLanguage) => {
    i18n.changeLanguage(value)
    setLanguage(value)
  }

  const handleAccordionChange = useCallback((value: string) => {
    // Prevent auto-scroll when opening accordion sections
    const scrollY = window.scrollY
    setOpenSection(value)
    requestAnimationFrame(() => {
      window.scrollTo(0, scrollY)
    })
  }, [])

  return (
    <div>
      <Accordion
        type="single"
        collapsible
        value={openSection}
        onValueChange={handleAccordionChange}
        className="w-full"
      >
        {/* General */}
        <AccordionItem value="general">
          <AccordionTrigger className="px-4 hover:no-underline">
            <div className="flex items-center gap-4">
              <Settings2 className="size-4" />
              <span>{t('General')}</span>
            </div>
          </AccordionTrigger>
          <AccordionContent className="px-4 space-y-4">
            <SettingItem>
              <Label htmlFor="languages" className="text-base font-normal">
                {t('Languages')}
              </Label>
              <Select defaultValue="en" value={language} onValueChange={handleLanguageChange}>
                <SelectTrigger id="languages" className="w-48">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {Object.entries(LocalizedLanguageNames).map(([key, value]) => (
                    <SelectItem key={key} value={key}>
                      {value}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </SettingItem>
            <SettingItem>
              <Label htmlFor="media-auto-load-policy" className="text-base font-normal">
                {t('Auto-load media')}
              </Label>
              <Select
                defaultValue="wifi-only"
                value={mediaAutoLoadPolicy}
                onValueChange={(value: TMediaAutoLoadPolicy) => setMediaAutoLoadPolicy(value)}
              >
                <SelectTrigger id="media-auto-load-policy" className="w-48">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value={MEDIA_AUTO_LOAD_POLICY.ALWAYS}>{t('Always')}</SelectItem>
                  {isSupportCheckConnectionType() && (
                    <SelectItem value={MEDIA_AUTO_LOAD_POLICY.WIFI_ONLY}>{t('Wi-Fi only')}</SelectItem>
                  )}
                  <SelectItem value={MEDIA_AUTO_LOAD_POLICY.NEVER}>{t('Never')}</SelectItem>
                </SelectContent>
              </Select>
            </SettingItem>
            <SettingItem>
              <Label htmlFor="autoplay" className="text-base font-normal">
                <div>{t('Autoplay')}</div>
                <div className="text-muted-foreground">{t('Enable video autoplay on this device')}</div>
              </Label>
              <Switch id="autoplay" checked={autoplay} onCheckedChange={setAutoplay} />
            </SettingItem>
            <SettingItem>
              <Label htmlFor="hide-untrusted-notes" className="text-base font-normal">
                {t('Hide untrusted notes')}
              </Label>
              <Switch
                id="hide-untrusted-notes"
                checked={hideUntrustedNotes}
                onCheckedChange={updateHideUntrustedNotes}
              />
            </SettingItem>
            <SettingItem>
              <Label htmlFor="hide-untrusted-interactions" className="text-base font-normal">
                {t('Hide untrusted interactions')}
              </Label>
              <Switch
                id="hide-untrusted-interactions"
                checked={hideUntrustedInteractions}
                onCheckedChange={updateHideUntrustedInteractions}
              />
            </SettingItem>
            <SettingItem>
              <Label htmlFor="hide-untrusted-notifications" className="text-base font-normal">
                {t('Hide untrusted notifications')}
              </Label>
              <Switch
                id="hide-untrusted-notifications"
                checked={hideUntrustedNotifications}
                onCheckedChange={updateHideUntrustedNotifications}
              />
            </SettingItem>
            <SettingItem>
              <Label htmlFor="hide-content-mentioning-muted-users" className="text-base font-normal">
                {t('Hide content mentioning muted users')}
              </Label>
              <Switch
                id="hide-content-mentioning-muted-users"
                checked={hideContentMentioningMutedUsers}
                onCheckedChange={setHideContentMentioningMutedUsers}
              />
            </SettingItem>
            <SettingItem>
              <Label htmlFor="nsfw-display-policy" className="text-base font-normal">
                {t('NSFW content display')}
              </Label>
              <Select
                value={nsfwDisplayPolicy}
                onValueChange={(value: TNsfwDisplayPolicy) => setNsfwDisplayPolicy(value)}
              >
                <SelectTrigger id="nsfw-display-policy" className="w-48">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value={NSFW_DISPLAY_POLICY.HIDE}>{t('Hide completely')}</SelectItem>
                  <SelectItem value={NSFW_DISPLAY_POLICY.HIDE_CONTENT}>{t('Show but hide content')}</SelectItem>
                  <SelectItem value={NSFW_DISPLAY_POLICY.SHOW}>{t('Show directly')}</SelectItem>
                </SelectContent>
              </Select>
            </SettingItem>
            <SettingItem>
              <Label htmlFor="quick-reaction" className="text-base font-normal">
                <div>{t('Quick reaction')}</div>
                <div className="text-muted-foreground">
                  {t('If enabled, you can react with a single click. Click and hold for more options')}
                </div>
              </Label>
              <Switch id="quick-reaction" checked={quickReaction} onCheckedChange={updateQuickReaction} />
            </SettingItem>
            {quickReaction && (
              <SettingItem>
                <Label htmlFor="quick-reaction-emoji" className="text-base font-normal">
                  {t('Quick reaction emoji')}
                </Label>
                <div className="flex items-center gap-2">
                  <Button
                    variant="ghost"
                    size="icon"
                    onClick={() => updateQuickReactionEmoji('+')}
                    className="text-muted-foreground hover:text-foreground"
                  >
                    <RotateCcw />
                  </Button>
                  <EmojiPickerDialog
                    onEmojiClick={(emoji) => {
                      if (!emoji) return
                      updateQuickReactionEmoji(emoji)
                    }}
                  >
                    <Button variant="ghost" size="icon" className="border">
                      <Emoji emoji={quickReactionEmoji} />
                    </Button>
                  </EmojiPickerDialog>
                </div>
              </SettingItem>
            )}
          </AccordionContent>
        </AccordionItem>

        {/* Appearance */}
        <AccordionItem value="appearance">
          <AccordionTrigger className="px-4 hover:no-underline">
            <div className="flex items-center gap-4">
              <Palette className="size-4" />
              <span>{t('Appearance')}</span>
            </div>
          </AccordionTrigger>
          <AccordionContent className="px-4 space-y-4">
            <div className="flex flex-col gap-2">
              <Label className="text-base">{t('Theme')}</Label>
              <div className="grid grid-cols-2 md:grid-cols-4 gap-4 w-full">
                {THEMES.map(({ key, label, icon }) => (
                  <OptionButton
                    key={key}
                    isSelected={themeSetting === key}
                    icon={icon}
                    label={t(label)}
                    onClick={() => setThemeSetting(key)}
                  />
                ))}
              </div>
            </div>
            {!isSmallScreen && (
              <div className="flex flex-col gap-2">
                <Label className="text-base">{t('Layout')}</Label>
                <div className="grid grid-cols-2 gap-4 w-full">
                  {LAYOUTS.map(({ key, label, icon }) => (
                    <OptionButton
                      key={key.toString()}
                      isSelected={enableSingleColumnLayout === key}
                      icon={icon}
                      label={t(label)}
                      onClick={() => updateEnableSingleColumnLayout(key)}
                    />
                  ))}
                </div>
              </div>
            )}
            <div className="flex flex-col gap-2">
              <Label className="text-base">{t('Notification list style')}</Label>
              <div className="grid grid-cols-2 gap-4 w-full">
                {NOTIFICATION_STYLES.map(({ key, label, icon }) => (
                  <OptionButton
                    key={key}
                    isSelected={notificationListStyle === key}
                    icon={icon}
                    label={t(label)}
                    onClick={() => updateNotificationListStyle(key)}
                  />
                ))}
              </div>
            </div>
            <div className="flex flex-col gap-2">
              <Label className="text-base">{t('Primary color')}</Label>
              <div className="grid grid-cols-4 gap-4 w-full">
                {Object.entries(PRIMARY_COLORS).map(([key, config]) => (
                  <OptionButton
                    key={key}
                    isSelected={primaryColor === key}
                    icon={
                      <div
                        className="size-8 rounded-full shadow-md"
                        style={{ backgroundColor: `hsl(${config.light.primary})` }}
                      />
                    }
                    label={t(config.name)}
                    onClick={() => setPrimaryColor(key as TPrimaryColor)}
                  />
                ))}
              </div>
            </div>
          </AccordionContent>
        </AccordionItem>

        {/* Relays */}
        <AccordionItem value="relays">
          <AccordionTrigger className="px-4 hover:no-underline">
            <div className="flex items-center gap-4">
              <Server className="size-4" />
              <span>{t('Relays')}</span>
            </div>
          </AccordionTrigger>
          <AccordionContent className="px-4">
            <RadixTabs value={relayTabValue} onValueChange={setRelayTabValue} className="space-y-4">
              <TabsList>
                <TabsTrigger value="favorite-relays">{t('Favorite Relays')}</TabsTrigger>
                <TabsTrigger value="mailbox">{t('Read & Write Relays')}</TabsTrigger>
              </TabsList>
              <TabsContent value="favorite-relays">
                <FavoriteRelaysSetting />
              </TabsContent>
              <TabsContent value="mailbox">
                <MailboxSetting />
              </TabsContent>
            </RadixTabs>
          </AccordionContent>
        </AccordionItem>

        {/* Wallet */}
        {!!pubkey && (
          <AccordionItem value="wallet">
            <AccordionTrigger className="px-4 hover:no-underline">
              <div className="flex items-center gap-4">
                <Wallet className="size-4" />
                <span>{t('Wallet')}</span>
              </div>
            </AccordionTrigger>
            <AccordionContent className="px-4 space-y-4">
              {isWalletConnected ? (
                <>
                  <div>
                    {walletInfo?.node.alias && (
                      <div className="mb-2">
                        {t('Connected to')} <strong>{walletInfo.node.alias}</strong>
                      </div>
                    )}
                    <AlertDialog>
                      <AlertDialogTrigger asChild>
                        <Button variant="destructive">{t('Disconnect Wallet')}</Button>
                      </AlertDialogTrigger>
                      <AlertDialogContent>
                        <AlertDialogHeader>
                          <AlertDialogTitle>{t('Are you absolutely sure?')}</AlertDialogTitle>
                          <AlertDialogDescription>
                            {t('You will not be able to send zaps to others.')}
                          </AlertDialogDescription>
                        </AlertDialogHeader>
                        <AlertDialogFooter>
                          <AlertDialogCancel>{t('Cancel')}</AlertDialogCancel>
                          <AlertDialogAction variant="destructive" onClick={() => disconnect()}>
                            {t('Disconnect')}
                          </AlertDialogAction>
                        </AlertDialogFooter>
                      </AlertDialogContent>
                    </AlertDialog>
                  </div>
                  <DefaultZapAmountInput />
                  <DefaultZapCommentInput />
                  <QuickZapSwitch />
                  <LightningAddressInput />
                </>
              ) : (
                <div className="flex items-center gap-2">
                  <Button className="bg-foreground hover:bg-foreground/90" onClick={() => launchModal()}>
                    {t('Connect Wallet')}
                  </Button>
                </div>
              )}
            </AccordionContent>
          </AccordionItem>
        )}

        {/* Post Settings */}
        {!!pubkey && (
          <AccordionItem value="posts">
            <AccordionTrigger className="px-4 hover:no-underline">
              <div className="flex items-center gap-4">
                <PencilLine className="size-4" />
                <span>{t('Post settings')}</span>
              </div>
            </AccordionTrigger>
            <AccordionContent className="px-4">
              <MediaUploadServiceSetting />
            </AccordionContent>
          </AccordionItem>
        )}

        {/* Emoji Packs */}
        {!!pubkey && (
          <AccordionItem value="emoji-packs">
            <AccordionTrigger className="px-4 hover:no-underline">
              <div className="flex items-center gap-4">
                <Smile className="size-4" />
                <span>{t('Emoji Packs')}</span>
              </div>
            </AccordionTrigger>
            <AccordionContent className="px-4">
              <Tabs
                value={emojiTab}
                tabs={[
                  { value: 'my-packs', label: 'My Packs' },
                  { value: 'explore', label: 'Explore' }
                ]}
                onTabChange={(tab) => setEmojiTab(tab as TEmojiTab)}
              />
              {emojiTab === 'my-packs' ? (
                <EmojiPackList />
              ) : (
                <NoteList
                  showKinds={[kinds.Emojisets]}
                  subRequests={[{ urls: BIG_RELAY_URLS, filter: {} }]}
                  hideUntrustedNotes={hideUntrustedNotes}
                />
              )}
            </AccordionContent>
          </AccordionItem>
        )}

        {/* System */}
        <AccordionItem value="system">
          <AccordionTrigger className="px-4 hover:no-underline">
            <div className="flex items-center gap-4">
              <Cog className="size-4" />
              <span>{t('System')}</span>
            </div>
          </AccordionTrigger>
          <AccordionContent className="px-4 space-y-4">
            <div className="space-y-2">
              <Label htmlFor="favicon-url" className="text-base font-normal">
                {t('Favicon URL')}
              </Label>
              <Input
                id="favicon-url"
                type="text"
                value={faviconUrlTemplate}
                onChange={(e) => setFaviconUrlTemplate(e.target.value)}
                placeholder={DEFAULT_FAVICON_URL_TEMPLATE}
              />
            </div>
            <SettingItem>
              <Label htmlFor="filter-out-onion-relays" className="text-base font-normal">
                {t('Filter out onion relays')}
              </Label>
              <Switch
                id="filter-out-onion-relays"
                checked={filterOutOnionRelays}
                onCheckedChange={(checked) => {
                  storage.setFilterOutOnionRelays(checked)
                  setFilterOutOnionRelays(checked)
                  dispatchSettingsChanged()
                }}
              />
            </SettingItem>
          </AccordionContent>
        </AccordionItem>
      </Accordion>

      {/* Non-accordion items */}
      {!!nsec && (
        <SettingItem
          className="clickable"
          onClick={() => {
            navigator.clipboard.writeText(nsec)
            setCopiedNsec(true)
            setTimeout(() => setCopiedNsec(false), 2000)
          }}
        >
          <div className="flex items-center gap-4">
            <KeyRound />
            <div>{t('Copy private key')} (nsec)</div>
          </div>
          {copiedNsec ? <Check /> : <Copy />}
        </SettingItem>
      )}
      {!!ncryptsec && (
        <SettingItem
          className="clickable"
          onClick={() => {
            navigator.clipboard.writeText(ncryptsec)
            setCopiedNcryptsec(true)
            setTimeout(() => setCopiedNcryptsec(false), 2000)
          }}
        >
          <div className="flex items-center gap-4">
            <KeyRound />
            <div>{t('Copy private key')} (ncryptsec)</div>
          </div>
          {copiedNcryptsec ? <Check /> : <Copy />}
        </SettingItem>
      )}
      <AboutInfoDialog>
        <SettingItem className="clickable">
          <div className="flex items-center gap-4">
            <Info />
            <div>{t('About')}</div>
          </div>
          <div className="flex gap-2 items-center">
            <div className="text-muted-foreground">
              v{import.meta.env.APP_VERSION} ({import.meta.env.GIT_COMMIT})
            </div>
          </div>
        </SettingItem>
      </AboutInfoDialog>
      <div className="p-4">
        <Donation />
      </div>
    </div>
  )
}

const SettingItem = forwardRef<HTMLDivElement, HTMLProps<HTMLDivElement>>(
  ({ children, className, ...props }, ref) => {
    return (
      <div
        className={cn(
          'flex justify-between select-none items-center px-4 min-h-9 [&_svg]:size-4 [&_svg]:shrink-0',
          className
        )}
        {...props}
        ref={ref}
      >
        {children}
      </div>
    )
  }
)
SettingItem.displayName = 'SettingItem'

const OptionButton = ({
  isSelected,
  onClick,
  icon,
  label
}: {
  isSelected: boolean
  onClick: () => void
  icon: React.ReactNode
  label: string
}) => {
  return (
    <button
      onClick={onClick}
      className={cn(
        'flex flex-col items-center gap-2 py-4 rounded-lg border-2 transition-all',
        isSelected ? 'border-primary' : 'border-border hover:border-muted-foreground/40'
      )}
    >
      <div className="flex items-center justify-center w-8 h-8">{icon}</div>
      <span className="text-xs font-medium">{label}</span>
    </button>
  )
}
