import { useCallback } from 'react'
import {
  ActionIcon,
  Indicator,
  Popover,
  Drawer,
  Stack,
  Text,
  Group,
  Box,
  UnstyledButton,
  Anchor,
  Divider,
} from '@pikku/mantine/core'
import { useDisclosure, useMediaQuery } from '@mantine/hooks'
import { asI18n } from '@pikku/react'
import { m } from '@/i18n/messages'
import { Bell, BellOff } from 'lucide-react'
import { useNavigate } from '@tanstack/react-router'
import { useQueryClient } from '@tanstack/react-query'
import { usePikkuQuery, usePikkuMutation } from '@perauset/functions-sdk/pikku/api.gen'

interface NotificationItem {
  notificationId: string
  type: string
  title: string
  body: string | null
  entityType: string | null
  entityId: string | null
  readAt: string | Date | null
  createdAt: string | Date
}

function entityLink(
  entityType: string | null,
  entityId: string | null,
): string | null {
  if (!entityType || !entityId) return null
  switch (entityType) {
    case 'task':
      return '/tasks'
    case 'stay':
      return '/stays'
    case 'boat_trip':
      return '/boats'
    case 'retreat':
      return '/retreats'
    default:
      return null
  }
}

function formatTimestamp(val: string | Date): string {
  const d = typeof val === 'string' ? new Date(val) : val
  const now = new Date()
  const diffMs = now.getTime() - d.getTime()
  const diffMin = Math.floor(diffMs / 60000)
  if (diffMin < 1) return 'Just now'
  if (diffMin < 60) return `${diffMin}m ago`
  const diffHr = Math.floor(diffMin / 60)
  if (diffHr < 24) return `${diffHr}h ago`
  const diffDays = Math.floor(diffHr / 24)
  if (diffDays < 7) return `${diffDays}d ago`
  return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })
}

function NotificationEntry({
  n,
  onRead,
}: {
  n: NotificationItem
  onRead: (id: string, link: string | null) => void
}) {
  const isRead = !!n.readAt
  const link = entityLink(n.entityType, n.entityId)

  return (
    <UnstyledButton
      onClick={() => onRead(n.notificationId, link)}
      style={{
        display: 'block',
        width: '100%',
        padding: '10px 12px',
        borderRadius: 8,
        backgroundColor: isRead ? 'transparent' : 'rgba(42, 123, 136, 0.04)',
        transition: 'background-color 0.15s ease',
      }}
    >
      <Group gap="xs" align="flex-start" wrap="nowrap">
        <Box
          style={{
            width: 8,
            height: 8,
            borderRadius: '50%',
            backgroundColor: isRead ? 'transparent' : '#2A7B88',
            flexShrink: 0,
            marginTop: 6,
          }}
        />
        <Box style={{ flex: 1, minWidth: 0 }}>
          <Group justify="space-between" gap="xs" wrap="nowrap">
            <Text size="sm" fw={isRead ? 400 : 600} lineClamp={1}>
              {asI18n(n.title)}
            </Text>
            <Text size="xs" c="dimmed" style={{ flexShrink: 0 }}>
              {asI18n(formatTimestamp(n.createdAt))}
            </Text>
          </Group>
          {n.body && (
            <Text size="xs" c="dimmed" lineClamp={1} mt={2}>
              {asI18n(n.body)}
            </Text>
          )}
        </Box>
      </Group>
    </UnstyledButton>
  )
}

export function NotificationBell() {
  const navigate = useNavigate()
  const queryClient = useQueryClient()
  const isMobile = useMediaQuery('(max-width: 768px)')
  const [popoverOpened, { toggle: togglePopover, close: closePopover }] =
    useDisclosure()
  const [drawerOpened, { toggle: toggleDrawer, close: closeDrawer }] =
    useDisclosure()

  const { data } = usePikkuQuery(
    'listNotifications',
    { limit: 5, offset: 0 },
    { refetchInterval: 30_000 },
  )

  const items = (data?.items ?? []) as NotificationItem[]
  const unreadCount = items.filter((n) => !n.readAt).length

  const markReadMutation = usePikkuMutation('markNotificationRead', {
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['listNotifications'] })
    },
  })

  const handleRead = useCallback(
    (notificationId: string, link: string | null) => {
      // Optimistic update
      queryClient.setQueryData<{ items?: NotificationItem[] }>(
        ['listNotifications', { limit: 5, offset: 0 }],
        (old) => {
          if (!old?.items) return old
          return {
            ...old,
            items: old.items.map((n) =>
              n.notificationId === notificationId
                ? { ...n, readAt: new Date().toISOString() }
                : n,
            ),
          }
        },
      )

      markReadMutation.mutate({ notificationId })

      if (link) {
        closePopover()
        closeDrawer()
        navigate({ to: link })
      }
    },
    [queryClient, markReadMutation, closePopover, closeDrawer, navigate],
  )

  const handleToggle = () => {
    if (isMobile) {
      toggleDrawer()
    } else {
      togglePopover()
    }
  }

  const bellButton = (
    <Indicator
      size={16}
      label={unreadCount > 0 ? asI18n(String(unreadCount)) : undefined}
      disabled={unreadCount === 0}
      color="red"
      offset={4}
      processing={unreadCount > 0}
    >
      <ActionIcon
        variant="subtle"
        color="gray"
        size="lg"
        onClick={handleToggle}
        aria-label={asI18n('Notifications')}
      >
        <Bell size={20} />
      </ActionIcon>
    </Indicator>
  )

  const content = (
    <Stack gap={0}>
      <Group justify="space-between" px="xs" py="xs">
        <Text fw={600} size="sm" style={{ fontFamily: '"Cormorant", serif' }}>
          {m.notifications_title()}
        </Text>
        {unreadCount > 0 && (
          <Text size="xs" c="teal" fw={500}>
            {m.notifications_unread_count({ count: unreadCount })}
          </Text>
        )}
      </Group>
      <Divider />
      {items.length === 0 ? (
        <Stack align="center" gap="xs" py="lg">
          <BellOff size={28} color="#aaa" />
          <Text size="sm" c="dimmed">
            {m.notifications_empty()}
          </Text>
        </Stack>
      ) : (
        <Stack gap={2} p={4}>
          {items.map((n) => (
            <NotificationEntry key={n.notificationId} n={n} onRead={handleRead} />
          ))}
        </Stack>
      )}
      <Divider />
      <Box py="xs" px="xs" style={{ textAlign: 'center' }}>
        <Anchor
          component="button"
          type="button"
          size="sm"
          onClick={() => {
            closePopover()
            closeDrawer()
            navigate({ to: '/notifications' })
          }}
        >
          {m.notifications_view_all()}
        </Anchor>
      </Box>
    </Stack>
  )

  if (isMobile) {
    return (
      <>
        {bellButton}
        <Drawer
          opened={drawerOpened}
          onClose={closeDrawer}
          position="bottom"
          size="60%"
          title={undefined}
          styles={{
            content: { borderTopLeftRadius: 16, borderTopRightRadius: 16 },
          }}
        >
          {content}
        </Drawer>
      </>
    )
  }

  return (
    <Popover
      opened={popoverOpened}
      onChange={(o) => {
        if (!o) closePopover()
      }}
      width={360}
      position="bottom-end"
      shadow="lg"
      radius="md"
    >
      <Popover.Target>{bellButton}</Popover.Target>
      <Popover.Dropdown p={0}>{content}</Popover.Dropdown>
    </Popover>
  )
}
