import { Feather } from '@expo/vector-icons'
import { useActiveProfile, useAuth } from '@state/AuthProvider'
import { useQuery } from '@tanstack/react-query'
import * as Application from 'expo-application'
import { Link, useRouter } from 'expo-router'
import { Pressable } from 'react-native'
import UserAvatar from 'src/components/common/UserAvatar'
import { ScreenScrollContainer } from 'src/components/layout'
import {
  BodyText,
  FootnoteText,
  LinkRowGroup,
  type LinkRowProps,
  SubheadText,
} from 'src/components/ui'
import { useConfirmDialog } from 'src/hooks/useConfirmDialog'
import { serverSoftwareDisplayName } from 'src/lib/branding'
import { useFeature } from 'src/lib/features'
import { newsroomQueries } from 'src/lib/queries/newsroom'
import { AccountStore, fullHandle } from 'src/state/accountStore'
import { openBrowserAsync } from 'src/utils'
import {
  Button,
  Group,
  Text,
  useTheme,
  useToastController,
  View,
  XStack,
  YStack,
} from 'tamagui'

export default function Page() {
  const theme = useTheme()
  const { profile: userCache } = useActiveProfile()
  const username = userCache?.username ?? ''
  const locked = !!userCache?.locked
  const activeAccount = AccountStore.activeAccount()
  const instance = activeAccount?.instance
  const isPixelfed = activeAccount?.type === 'pixelfed'
  const notificationPoliciesEnabled = useFeature('notification_policies')
  const tapestryEnabled = useFeature('tapestry')
  // Mastodon Pass Phase 4 §5.3 — Newsroom is Pixelfed-only; skip the
  // timeline fetch entirely on Mastodon-active sessions so the row's
  // unread badge isn't computed against an endpoint that 404s.
  const { data: newsroomItems } = useQuery({
    ...newsroomQueries.timeline(),
    enabled: isPixelfed,
  })
  const newsroomUnread = newsroomItems?.length ?? 0
  const buildVersion = 1
  const version = Application.nativeApplicationVersion + '.' + buildVersion

  const { removeAccount } = useAuth()
  const { confirm, dialog: confirmDialog } = useConfirmDialog()
  const router = useRouter()
  const toast = useToastController()

  const openLink = async (path: string) => {
    openBrowserAsync('https://' + instance + '/' + path)
  }

  const activeHandle = activeAccount
    ? fullHandle(activeAccount)
    : `@${username}@${instance ?? ''}`

  const handleSignOutOfThis = async () => {
    const ok = await confirm({
      title: `Sign out of ${activeHandle}?`,
      message:
        'This removes the account from this device. Your posts and follows on the server are not affected.',
      confirmLabel: 'Sign out',
      destructive: true,
    })
    if (!ok) return
    const handle = activeHandle
    const activeId = AccountStore.activeId()
    if (!activeId) return
    await removeAccount(activeId)
    toast.show(`Signed out of ${handle}`, { preset: 'success' })
    // The Settings screen sits outside `Stack.Protected guard={!!user}`,
    // so an explicit redirect is needed when no fallback account remains.
    if (!AccountStore.activeId()) router.replace('/(public)/login' as any)
  }

  const accountRows: LinkRowProps[] = [
    {
      kind: 'internal',
      icon: 'user',
      title: 'Profile',
      description: 'Avatar, bio, and display name.',
      path: '/settings/profile',
    },
    ...(locked
      ? ([
          {
            kind: 'internal',
            icon: 'user-plus',
            title: 'Follow Requests',
            description: 'Review accounts waiting to follow you.',
            path: '/profile/follow-requests/',
          },
        ] satisfies LinkRowProps[])
      : []),
    {
      kind: 'internal',
      icon: 'tag',
      title: 'Followed Hashtags',
      description: 'Manage tags you subscribe to.',
      path: '/hashtag/followedTags',
    },
    {
      kind: 'internal',
      icon: 'lock',
      title: 'Privacy & Relationships',
      description: 'Account privacy, blocks, and mutes.',
      path: '/settings/privacy',
    },
  ]

  const contentRows: LinkRowProps[] = [
    {
      kind: 'internal',
      icon: 'life-buoy',
      title: 'Accessibility',
      description: 'Motion, captions, and assistive options.',
      path: '/settings/accessibility/',
    },
    {
      kind: 'internal',
      icon: 'droplet',
      title: 'Appearance',
      description: 'Theme and display preferences.',
      path: '/settings/appearance/',
    },
    // Holistic Pass 4 Phase 5.1 — Mastodon-only. Pixelfed's `/api/v1/lists`
    // returns `[]` (server stub), so the row hides on Pixelfed accounts to
    // avoid leading users to a screen with nothing to manage.
    ...(isPixelfed
      ? []
      : ([
          {
            kind: 'internal',
            icon: 'list',
            title: 'Lists',
            description: 'Reorder your lists for the home filter.',
            path: '/settings/lists/',
          },
        ] satisfies LinkRowProps[])),
    // Compose Redesign Phase 1: device-level compose preferences
    // (Media Editor, Auto-Resize info) moved out of the per-post
    // `PostOptionsSheet` and into a dedicated settings screen. The
    // composer's "Post options" header menu went away with the same
    // change — per-post options return in Phase 4's overflow sheet.
    {
      kind: 'internal',
      icon: 'edit-2',
      title: 'Compose',
      description: 'Media editor and resize preferences.',
      path: '/settings/compose',
    },
    {
      kind: 'internal',
      icon: 'hard-drive',
      title: 'Storage',
      description: 'Cache size, limits, and auto-clear.',
      path: '/settings/storage',
    },
  ]

  const notificationRows: LinkRowProps[] = [
    // Push Notifications row intentionally omitted: device-push registration
    // is fully disabled in this build (see `src/lib/push.ts`). Restore this
    // row when the server gateway / RN Web Push story is reworked.
    ...(notificationPoliciesEnabled
      ? ([
          {
            kind: 'internal',
            icon: 'filter',
            title: 'Notification Policy',
            description: 'Filter who can send you notifications.',
            path: '/settings/notifications/policy',
          },
          {
            kind: 'internal',
            icon: 'inbox',
            title: 'Filtered Requests',
            description: 'Review notifications held by your policy.',
            path: '/settings/notifications/requests',
          },
        ] satisfies LinkRowProps[])
      : []),
  ]

  const aboutRows: LinkRowProps[] = [
    // Mastodon Pass Phase 4 §5.3 / §9.8 #41 — Newsroom is Pixelfed-only
    // (`api/pixelfed/v1/newsroom/*`). Hide the row outright on Mastodon
    // accounts rather than greying it; per plan §9.8 absence is cleaner
    // than "coming soon" copy users will read as a defect.
    ...(isPixelfed
      ? ([
          {
            kind: 'internal',
            icon: 'radio',
            title: `${instance ?? 'Server'} news`,
            description: 'Announcements from your instance admin.',
            path: '/settings/newsroom/',
            badge: newsroomUnread,
          },
        ] satisfies LinkRowProps[])
      : []),
    {
      kind: 'internal',
      icon: 'heart',
      title: 'Open Source',
      description: 'Credits and ways to contribute.',
      path: '/settings/open-source/',
    },
    {
      kind: 'external',
      icon: 'code',
      title: 'Source code',
      description: 'Per-build source archives for this app.',
      url: 'https://halflig.ht/source/',
    },
    {
      kind: 'internal',
      icon: 'align-left',
      title: 'Legal',
      description: 'Privacy policy and terms of service.',
      path: '/settings/legal/',
    },
    {
      kind: 'action',
      icon: 'trash',
      title: 'Delete Account',
      description: 'Permanently remove your account.',
      tone: 'danger',
      // Mastodon Pass 3 Phase 2 §3.1 — Pixelfed exposes its own
      // remove-account flow under `settings/remove/request/permanent`;
      // Mastodon's stable destination is `auth/edit` (the user's account
      // settings page, where the Delete section lives). Per-instance
      // variation in the Mastodon path is ruled out by `config/routes.rb`
      // `devise_for :users`.
      onPress: () =>
        openLink(isPixelfed ? 'settings/remove/request/permanent' : 'auth/edit'),
      trailingIcon: 'external-link',
    },
    {
      kind: 'value',
      icon: 'info',
      title: 'Version',
      value: version,
    },
  ]

  return (
    <ScreenScrollContainer variant="scroll" header="Settings">
      <YStack px="$5" pt="$4" pb="$2" gap="$2">
        <BodyText tone="secondary">
          Configure your account, notifications, and privacy.
        </BodyText>
      </YStack>

      <YStack px="$5" pt="$5" gap="$3">
        <FootnoteText tone="tertiary" letterSpacing={0.4} textTransform="uppercase">
          Accounts
        </FootnoteText>
        <Group orientation="vertical">
          <Group.Item>
            <Link href={'/settings/accounts' as any} asChild>
              <Pressable
                style={({ pressed }) => ({ opacity: pressed ? 0.7 : 1 })}
                accessibilityRole="button"
                accessibilityLabel="Manage accounts"
              >
                <XStack
                  bg="$backgroundSecondary"
                  px="$4"
                  py="$3"
                  gap="$3"
                  alignItems="center"
                >
                  <UserAvatar
                    url={activeAccount?.avatarUrl ?? userCache?.avatar ?? null}
                    size="md"
                    initial={
                      activeAccount?.displayName || activeAccount?.username || username
                    }
                  />
                  <YStack flex={1} gap={2}>
                    <XStack alignItems="center" gap="$2">
                      <SubheadText emphasis="strong" numberOfLines={1} flexShrink={1}>
                        {activeAccount?.displayName ||
                          userCache?.display_name ||
                          username}
                      </SubheadText>
                      {/*
                        Mastodon Pass Phase 4 §5.3 / §9.8 #44 — small
                        server-type pill so the active-account row is
                        legible at a glance when both account types are
                        signed in. Pill copy comes from
                        `serverSoftwareDisplayName(type)` so a future
                        i18n rework swaps the source in one place.
                      */}
                      {activeAccount ? (
                        <View
                          backgroundColor="$backgroundTertiary"
                          borderRadius="$2"
                          px="$2"
                          py={1}
                        >
                          <FootnoteText tone="secondary" numberOfLines={1}>
                            {serverSoftwareDisplayName(activeAccount.type)}
                          </FootnoteText>
                        </View>
                      ) : null}
                    </XStack>
                    <FootnoteText tone="secondary" numberOfLines={1}>
                      {activeHandle}
                    </FootnoteText>
                  </YStack>
                  <View flexDirection="row" alignItems="center">
                    <Feather
                      name="chevron-right"
                      size={16}
                      color={theme.colorTertiary.val as string}
                    />
                  </View>
                </XStack>
              </Pressable>
            </Link>
          </Group.Item>
        </Group>
      </YStack>

      <LinkRowGroup header="Account" rows={accountRows} />
      <LinkRowGroup header="Content" rows={contentRows} />
      {tapestryEnabled ? (
        <LinkRowGroup
          header="Discover"
          rows={[
            {
              kind: 'internal',
              icon: 'activity',
              title: 'The Weave',
              description: "Your instance's collective gestures, by the minute.",
              path: '/tapestry',
            },
          ]}
        />
      ) : null}
      <LinkRowGroup header="Notifications" rows={notificationRows} />
      <LinkRowGroup header="About" rows={aboutRows} />

      <YStack px="$5" pt="$6" pb="$6">
        <Button
          variant="outlined"
          backgroundColor="transparent"
          borderColor={theme.colorDanger.val}
          onPress={() => handleSignOutOfThis()}
          transition="quick"
          pressStyle={{ opacity: 0.75, scale: 0.99 }}
        >
          <Text color={theme.colorDanger.val} fontWeight="600">
            Sign out of {activeHandle}
          </Text>
        </Button>
      </YStack>

      {confirmDialog}
    </ScreenScrollContainer>
  )
}
