import {useMemo} from 'react'
import {View} from 'react-native'
import {type AppBskyNotificationDefs} from '@atproto/api'
import {Trans, useLingui} from '@lingui/react/macro'

import {useNotificationSettingsUpdateMutation} from '#/state/queries/notifications/settings'
import {atoms as a, platform, useTheme} from '#/alf'
import * as Toggle from '#/components/forms/Toggle'
import {Loader} from '#/components/Loader'
import {Text} from '#/components/Typography'
import {useAnalytics} from '#/analytics'
import {Divider} from '../../components/SettingsList'

export function PreferenceControls({
  name,
  syncOthers,
  preference,
  allowDisableInApp = true,
}: {
  name: Exclude<keyof AppBskyNotificationDefs.Preferences, '$type'>
  /**
   * Keep other prefs in sync with `name`. For use in the "everything else" category
   * which groups starterpack joins + verified + unverified notifications into a single toggle.
   */
  syncOthers?: Exclude<keyof AppBskyNotificationDefs.Preferences, '$type'>[]
  preference?:
    | AppBskyNotificationDefs.Preference
    | AppBskyNotificationDefs.FilterablePreference
    | AppBskyNotificationDefs.ChatPreference
  allowDisableInApp?: boolean
}) {
  if (!preference)
    return (
      <View style={[a.w_full, a.pt_5xl, a.align_center]}>
        <Loader size="xl" />
      </View>
    )

  return (
    <Inner
      name={name}
      syncOthers={syncOthers}
      preference={preference}
      allowDisableInApp={allowDisableInApp}
    />
  )
}

export function Inner({
  name,
  syncOthers = [],
  preference,
  allowDisableInApp,
}: {
  name: Exclude<keyof AppBskyNotificationDefs.Preferences, '$type'>
  syncOthers?: Exclude<keyof AppBskyNotificationDefs.Preferences, '$type'>[]
  preference:
    | AppBskyNotificationDefs.Preference
    | AppBskyNotificationDefs.FilterablePreference
    | AppBskyNotificationDefs.ChatPreference
  allowDisableInApp: boolean
}) {
  const t = useTheme()
  const {t: l} = useLingui()
  const ax = useAnalytics()
  const {mutate} = useNotificationSettingsUpdateMutation()

  const channels = useMemo(() => {
    const arr = []
    if ('list' in preference && preference.list) arr.push('list')
    if (preference.push) arr.push('push')
    return arr
  }, [preference])

  const onChangeChannels = (change: string[]) => {
    const newPreference = {
      ...preference,
      ...('list' in preference ? {list: change.includes('list')} : {}),
      push: change.includes('push'),
    } as typeof preference

    const metrics: {name: string; push: boolean; list?: boolean} = {
      name,
      push: newPreference.push,
    }
    if ('list' in newPreference) {
      metrics.list = newPreference.list
    }
    ax.metric('activityPreference:changeChannels', metrics)

    mutate({
      [name]: newPreference,
      ...Object.fromEntries(syncOthers.map(key => [key, newPreference])),
    })
  }

  const onChangeFilter = ([change]: string[]) => {
    if (change !== 'all' && change !== 'follows' && change !== 'accepted')
      throw new Error('Invalid filter')

    const newPreference = {
      ...preference,
      include: change,
    } satisfies typeof preference

    ax.metric('activityPreference:changeFilter', {name, value: change})

    mutate({
      [name]: newPreference,
      ...Object.fromEntries(syncOthers.map(key => [key, newPreference])),
    })
  }

  return (
    <View style={[a.gap_sm]}>
      <Toggle.Group
        type="checkbox"
        label={l`Select your preferred notification channels`}
        values={channels}
        onChange={onChangeChannels}>
        <View style={[a.gap_sm]}>
          <Toggle.Item
            label={l`Receive push notifications`}
            name="push"
            style={[
              a.py_xs,
              platform({
                native: [a.justify_between],
                web: [a.flex_row_reverse, a.gap_sm],
              }),
            ]}>
            <Toggle.LabelText
              style={[t.atoms.text, a.font_normal, a.text_md, a.flex_1]}>
              <Trans>Push notifications</Trans>
            </Toggle.LabelText>
            <Toggle.Platform />
          </Toggle.Item>
          {allowDisableInApp && (
            <Toggle.Item
              label={l`Receive in-app notifications`}
              name="list"
              style={[
                a.py_xs,
                platform({
                  native: [a.justify_between],
                  web: [a.flex_row_reverse, a.gap_sm],
                }),
              ]}>
              <Toggle.LabelText
                style={[t.atoms.text, a.font_normal, a.text_md, a.flex_1]}>
                <Trans>In-app notifications</Trans>
              </Toggle.LabelText>
              <Toggle.Platform />
            </Toggle.Item>
          )}
        </View>
      </Toggle.Group>
      {'include' in preference && (
        <>
          <Divider />
          <Text style={[a.font_semi_bold, a.text_md]}>
            <Trans>From</Trans>
          </Text>
          <Toggle.Group
            type="radio"
            label={l`Filter who you receive notifications from`}
            values={[preference.include]}
            onChange={onChangeFilter}
            disabled={channels.length === 0}>
            <View style={[a.gap_sm]}>
              <Toggle.Item highlightRow label={l`Everyone`} name="all">
                {({selected}) => (
                  <Toggle.RadioWithLabel
                    label={l`Everyone`}
                    selected={selected}
                  />
                )}
              </Toggle.Item>
              {name === 'chat' ? (
                <Toggle.Item
                  highlightRow
                  label={l`Accepted conversations`}
                  name="accepted">
                  {({selected}) => (
                    <Toggle.RadioWithLabel
                      label={l`Accepted conversations`}
                      selected={selected}
                    />
                  )}
                </Toggle.Item>
              ) : (
                <Toggle.Item
                  highlightRow
                  label={l`People I follow`}
                  name="follows">
                  {({selected}) => (
                    <Toggle.RadioWithLabel
                      label={l`People I follow`}
                      selected={selected}
                    />
                  )}
                </Toggle.Item>
              )}
            </View>
          </Toggle.Group>
        </>
      )}
    </View>
  )
}
