import { useQuery } from '@tanstack/react-query'
import type { ErrorBoundaryProps } from 'expo-router'
import { ActivityIndicator } from 'react-native'
import { ErrorState } from 'src/components/common/ErrorState'
import { ScreenScrollContainer } from 'src/components/layout'
import { Card, FieldHelperText, FieldTitle } from 'src/components/ui'
import { listScopeKeys, useCacheMutation } from 'src/hooks/mutations/cacheMutation'
import { updateNotificationPolicy } from 'src/lib/api'
import { haptic } from 'src/lib/haptics'
import { queryKeys } from 'src/lib/queries/keys'
import { notificationQueries } from 'src/lib/queries/notifications'
import {
  Button,
  Separator,
  Text,
  useTheme,
  useToastController,
  View,
  XStack,
  YStack,
} from 'tamagui'

type PolicyDecision = 'accept' | 'filter' | 'drop'

type PolicyKey =
  | 'for_not_following'
  | 'for_not_followers'
  | 'for_new_accounts'
  | 'for_private_mentions'
  | 'for_limited_accounts'

const FIELDS: { key: PolicyKey; title: string; description: string }[] = [
  {
    key: 'for_not_following',
    title: 'People you don’t follow',
    description: 'Until you manually approve them',
  },
  {
    key: 'for_not_followers',
    title: 'People not following you',
    description: 'Including people who have been following you fewer than a few days',
  },
  {
    key: 'for_new_accounts',
    title: 'New accounts',
    description: 'Created within the past 30 days',
  },
  {
    key: 'for_private_mentions',
    title: 'Unsolicited private mentions',
    description: 'Filtered unless it’s in reply to your own mention',
  },
  {
    key: 'for_limited_accounts',
    title: 'Moderated accounts',
    description: 'Limited by server moderators',
  },
]

const DECISIONS: PolicyDecision[] = ['accept', 'filter', 'drop']

export function ErrorBoundary({ error, retry }: ErrorBoundaryProps) {
  return <ErrorState message={error.message} onRetry={retry} />
}

export default function Page() {
  const theme = useTheme()
  const toast = useToastController()
  const { data, status, error, refetch } = useQuery(notificationQueries.policy())

  const mutation = useCacheMutation<unknown, { key: PolicyKey; value: PolicyDecision }>({
    mutationFn: ({ key, value }) => updateNotificationPolicy({ [key]: value }),
    snapshotKeys: () => listScopeKeys(notificationQueries.policy().queryKey),
    applyOptimistic: (qc, { key, value }) => {
      qc.setQueryData(notificationQueries.policy().queryKey, (old: any) => ({
        ...old,
        [key]: value,
      }))
    },
    onError: () => {
      haptic.error()
      toast.show('Update failed', {
        message: 'Unable to update notification policy.',
        preset: 'error',
      })
    },
    onSuccess: (_data, _vars, qc) => {
      haptic.success()
      // A policy change alters what the server delivers for both v1 and v2
      // notification lists and the filtered-requests queue. Prefix-invalidate
      // so every notification tab pulls fresh data on next focus.
      qc.invalidateQueries({ queryKey: queryKeys.notifications.allPrefix() })
    },
  })

  if (status === 'pending') {
    return (
      <ScreenScrollContainer variant="scroll" header="Notification Policy">
        <View flex={1} justifyContent="center" alignItems="center" py="$10">
          <ActivityIndicator color={theme.color.val} />
        </View>
      </ScreenScrollContainer>
    )
  }

  if (status === 'error') {
    return <ErrorState message={(error as any)?.message} onRetry={refetch} />
  }

  const current = (data ?? {}) as Record<PolicyKey, PolicyDecision>

  return (
    <ScreenScrollContainer variant="scroll" header="Notification Policy">
      <View p="$4">
        <Text fontSize="$3" color={theme.colorSecondary.val}>
          Control how notifications are handled from different groups of senders. Accept
          delivers normally, Filter routes to a separate request queue, Drop discards
          silently.
        </Text>
      </View>
      {FIELDS.map((f, i) => {
        const value = current[f.key] ?? 'accept'
        return (
          <View key={f.key}>
            <Card tone="tertiary" gap="$2">
              <YStack gap="$1">
                <FieldTitle>{f.title}</FieldTitle>
                <FieldHelperText>{f.description}</FieldHelperText>
              </YStack>
              <XStack gap="$2">
                {DECISIONS.map((d) => {
                  const selected = value === d
                  return (
                    <Button
                      key={d}
                      size="$3"
                      flex={1}
                      bg={selected ? theme.interactiveActive.val : theme.background.val}
                      borderColor={theme.borderColor.val}
                      borderWidth={1}
                      borderRadius="$3"
                      borderCurve="continuous"
                      pressStyle={{ opacity: 0.8, scale: 0.98 }}
                      disabled={mutation.isPending}
                      onPress={() => {
                        if (selected) return
                        haptic.selection()
                        mutation.mutate({ key: f.key, value: d })
                      }}
                    >
                      <Text
                        fontSize="$2"
                        fontWeight="bold"
                        color={selected ? theme.background.val : theme.color.val}
                      >
                        {d.charAt(0).toUpperCase() + d.slice(1)}
                      </Text>
                    </Button>
                  )
                })}
              </XStack>
            </Card>
            {i < FIELDS.length - 1 ? <Separator borderColor="$borderColor" /> : null}
          </View>
        )
      })}
    </ScreenScrollContainer>
  )
}
