import { Feather } from '@expo/vector-icons'
import { useEffect, useState } from 'react'
import { Platform } from 'react-native'
import { useInstalled, usePaired, useReachability } from 'react-native-watch-connectivity'
import {
  getWatchHandoffSnapshot,
  pushActiveHandoff,
  revokeOnWatch,
  subscribeToHandoffEvents,
} from 'src/lib/watch/handoff'
import { AccountStore } from 'src/state/accountStore'
import { Button, Text, useTheme, useToastController, View, XStack, YStack } from 'tamagui'
import { BodyText, FootnoteText, SubheadText } from '../ui'

// Settings → Accounts → Apple Watch row.
//
// Surfaces three pieces of state:
//   - Pairing / install: from rnwc's `usePaired` + `useInstalled` hooks.
//     Both are platform-aware — Android stubs return false unconditionally,
//     so the parent collapses to nothing on non-iOS.
//   - Reachability: live-updating "watch is reachable right now" signal.
//     Used purely as a hint pill; actions still fire when unreachable
//     because `WCSession.updateApplicationContext` is queued for delivery.
//   - Handoff freshness: subscribes to this process's handoff event
//     stream so the "Synced Nm ago" line refreshes every time we push
//     or revoke. A 30s ticker re-renders the relative-time string
//     without a new tool round-trip.
//
// Two actions:
//   - Re-sync from iPhone — bypasses dedupe and re-pushes the active
//     account's handoff payload.
//   - Sign out on Watch — fires a `revoke` message for the active
//     account, leaving the phone-side registry untouched. The watch's
//     WCSession receiver wipes its keychain + AuthState, lands on
//     EmptyAuthView. Has no destructive effect on the phone.
//
// The component renders nothing when the watch isn't paired — the row
// is purely opt-in based on the user's hardware.

export function AppleWatchRow() {
  // Calling these on Android is safe — both modules ship Android stubs
  // that always return false — but no need to import the hook for a
  // guaranteed-false return. Render the platform gate at the same
  // boundary as the runtime guard so a future Android variant slots
  // in symmetrically.
  if (Platform.OS !== 'ios') return null
  return <AppleWatchRowInner />
}

function AppleWatchRowInner() {
  const theme = useTheme()
  const toast = useToastController()
  const paired = usePaired()
  const installed = useInstalled()
  const reachable = useReachability()
  const [tick, setTick] = useState(0)

  // Re-render on every handoff/revoke + every 30s so the "Synced Nm
  // ago" line stays current. Both subscriptions are cheap.
  useEffect(() => {
    const unsub = subscribeToHandoffEvents(() => setTick((t) => t + 1))
    const id = setInterval(() => setTick((t) => t + 1), 30_000)
    return () => {
      unsub()
      clearInterval(id)
    }
  }, [])

  if (!paired) return null

  const activeAccount = AccountStore.activeAccount()
  // Touch tick so the linter doesn't flag the variable as unused; the
  // useState read above is the actual mechanism keeping the relative
  // time fresh.
  void tick
  const { lastHandoffAt } = getWatchHandoffSnapshot()
  const status = installed
    ? lastHandoffAt
      ? `Synced ${relativeTime(lastHandoffAt)}`
      : 'Not yet synced'
    : 'Watch app installing — sync when ready'

  const onResync = () => {
    if (!activeAccount) {
      toast.show('No active account to sync', { preset: 'error' })
      return
    }
    pushActiveHandoff('user-resync')
    toast.show(`Re-syncing @${activeAccount.username}`, { preset: 'success' })
  }

  const onSignOutOnWatch = () => {
    if (!activeAccount) return
    revokeOnWatch(activeAccount.accountId)
    toast.show(`Signed out of @${activeAccount.username} on Watch`, {
      preset: 'success',
    })
  }

  return (
    <YStack
      backgroundColor="$backgroundSecondary"
      borderRadius="$4"
      px="$4"
      py="$3"
      gap="$3"
    >
      <XStack alignItems="center" gap="$3">
        <View
          width={36}
          height={36}
          borderRadius={18}
          backgroundColor="$backgroundTertiary"
          alignItems="center"
          justifyContent="center"
        >
          <Feather name="watch" size={18} color={theme.color.val as string} />
        </View>
        <YStack flex={1} gap={2}>
          <SubheadText emphasis="strong">Apple Watch</SubheadText>
          <FootnoteText tone="secondary" numberOfLines={1}>
            {status}
          </FootnoteText>
        </YStack>
        {reachable ? (
          <View
            width={8}
            height={8}
            borderRadius={4}
            backgroundColor={theme.accent?.val ?? '$color'}
          />
        ) : null}
      </XStack>

      {!installed ? (
        <BodyText tone="secondary">
          Open the Watch app on your iPhone and ensure Halflight is installed.
        </BodyText>
      ) : null}

      {installed && activeAccount ? (
        <XStack gap="$2">
          <Button
            flex={1}
            size="$3"
            onPress={onResync}
            icon={
              <Feather name="refresh-cw" size={14} color={theme.color.val as string} />
            }
          >
            <Button.Text>Re-sync</Button.Text>
          </Button>
          <Button
            flex={1}
            size="$3"
            variant="outlined"
            backgroundColor="transparent"
            borderColor={theme.colorDanger.val}
            onPress={onSignOutOnWatch}
          >
            <Text color={theme.colorDanger.val as string} fontWeight="600">
              Sign out on Watch
            </Text>
          </Button>
        </XStack>
      ) : null}
    </YStack>
  )
}

// Keep the relative-time formatter local so the row doesn't pull in a
// shared util. Same shape as the watch's own `RelativeDateTimeFormatter`-
// driven copy on the Account screen — kept symmetrical for QA.
function relativeTime(epochMs: number): string {
  const seconds = Math.max(0, Math.floor((Date.now() - epochMs) / 1000))
  if (seconds < 60) return 'just now'
  const minutes = Math.floor(seconds / 60)
  if (minutes < 60) return `${minutes}m ago`
  const hours = Math.floor(minutes / 60)
  if (hours < 24) return `${hours}h ago`
  const days = Math.floor(hours / 24)
  return `${days}d ago`
}
