import { ColorMode, useTheme } from '@context-providers/theme-context-provider'
import { MoonIcon, SunIcon } from '@radix-ui/react-icons'

import { useCallback } from 'react'
import { flushSync } from 'react-dom'

import { Button } from '@postxl/ui-components'

export const ColorModeToggle = ({
  onClick,
  __e2e_test_id__,
}: {
  onClick?: (nextMode: ColorMode) => void
  __e2e_test_id__?: string
}) => {
  const { colorMode, setColorMode } = useTheme()

  const toggleColorMode = useCallback(
    async (event: React.MouseEvent<HTMLButtonElement>) => {
      const isDark = colorMode === 'dark'
      const nextMode = isDark ? 'light' : 'dark'

      try {
        // Fallback for browsers that don't support View Transitions or use reduced motion
        const isReducedMotion = globalThis.matchMedia('(prefers-reduced-motion: reduce)').matches
        if (!document.startViewTransition || isReducedMotion) {
          setColorMode(nextMode)
          return
        }

        const { clientX: x, clientY: y } = event

        // Calculate the radius to cover the entire screen from the click position
        const endRadius = Math.hypot(Math.max(x, globalThis.innerWidth - x), Math.max(y, globalThis.innerHeight - y))

        // Determine direction:
        // If going to light (isDark is true), we want to reverse (Dark shrinks).
        // If going to dark (isDark is false), we want normal (Dark grows).
        const isReverse = isDark

        if (isReverse) {
          document.documentElement.setAttribute('data-theme-transition', 'reverse')
        }

        const transition = document.startViewTransition(() => {
          // Force a synchronous update so the DOM changes before the transition starts
          flushSync(() => {
            setColorMode(nextMode)
          })
        })

        // Wait for the pseudo-elements to be created
        await transition.ready

        // Animate the clip-path
        // If reverse (Dark -> Light): Animate OLD (Dark) shrinking from full to 0
        // If normal (Light -> Dark): Animate NEW (Dark) growing from 0 to full
        const keyframes = isReverse
          ? { clipPath: [`circle(${endRadius}px at ${x}px ${y}px)`, `circle(0px at ${x}px ${y}px)`] }
          : { clipPath: [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`] }

        const pseudoElement = isReverse ? '::view-transition-old(root)' : '::view-transition-new(root)'

        document.documentElement.animate(keyframes, {
          duration: 250,
          easing: 'ease-out',
          pseudoElement,
          fill: 'forwards',
        })

        // Cleanup
        await transition.finished
        if (isReverse) {
          document.documentElement.removeAttribute('data-theme-transition')
        }
      } catch (error) {
        console.warn('View transition failed, falling back to instant toggle:', error)
        setColorMode(nextMode)
      }

      onClick?.(nextMode)
    },
    [colorMode, onClick, setColorMode],
  )

  return (
    <Button
      variant="ghost"
      size="icon"
      onClick={toggleColorMode}
      className="size-8 rounded-full bg-accent"
      __e2e_test_id__={__e2e_test_id__}
    >
      <SunIcon className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
      <MoonIcon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
      <span className="sr-only">Toggle theme</span>
    </Button>
  )
}
