---
import { Button } from '@/components/ui/button'
import { Icon } from 'astro-icon/components'
---

<Button
  id="theme-toggle"
  variant="ghost"
  size="icon"
  title="Toggle theme"
  className="-my-2 -me-2 size-8"
>
  <Icon name="lucide:sun" class="size-4 dark:hidden" />
  <Icon name="lucide:moon" class="absolute hidden size-4 dark:block" />
  <span class="sr-only">Toggle theme</span>
</Button>

<script is:inline data-astro-rerun>
  ;(() => {
    const theme = (() => {
      const stored = localStorage?.getItem('theme') ?? ''
      if (['dark', 'light'].includes(stored)) return stored
      return window.matchMedia('(prefers-color-scheme: dark)').matches
        ? 'dark'
        : 'light'
    })()

    document.documentElement.setAttribute('data-theme', theme)
    window.localStorage.setItem('theme', theme)
  })()
</script>

<script>
  const VIEW_TRANSITION_STYLE_ID = 'view-transition-style'
  const VIEW_TRANSITION_STYLE = `
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none;
    mix-blend-mode: normal;
  }

  [data-theme='dark']::view-transition-old(root) {
    z-index: 1;
  }

  [data-theme='dark']::view-transition-new(root) {
    z-index: 999;
  }

  ::view-transition-old(root) {
    z-index: 999;
  }

  ::view-transition-new(root) {
    z-index: 1;
  }
  `

  const setTheme = (newTheme) => {
    const element = document.documentElement

    element.classList.add('[&_*]:transition-none')
    element.setAttribute('data-theme', newTheme)
    localStorage.setItem('theme', newTheme)
    window.getComputedStyle(element).getPropertyValue('opacity')

    requestAnimationFrame(() => {
      element.classList.remove('[&_*]:transition-none')
    })

    ensureViewTransitionStyle()
  }

  const ensureViewTransitionStyle = () => {
    if (!('startViewTransition' in document)) return
    if (document.getElementById(VIEW_TRANSITION_STYLE_ID)) return

    const styleElement = document.createElement('style')
    styleElement.id = VIEW_TRANSITION_STYLE_ID
    styleElement.textContent = VIEW_TRANSITION_STYLE
    document.head.appendChild(styleElement)
  }

  const handleToggleClick = (event) => {
    const element = document.documentElement
    const currentTheme =
      element.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'
    const newTheme = currentTheme === 'dark' ? 'light' : 'dark'

    const prefersReducedMotion = window.matchMedia(
      '(prefers-reduced-motion: reduce)',
    ).matches

    if (prefersReducedMotion) {
      setTheme(newTheme)
      return
    }

    if (!document.startViewTransition || !event) {
      setTheme(newTheme)
      return
    }

    const x = event.clientX ?? window.innerWidth / 2
    const y = event.clientY ?? window.innerHeight / 2
    const endRadius = Math.hypot(
      Math.max(x, window.innerWidth - x),
      Math.max(y, window.innerHeight - y),
    )

    try {
      document
        .startViewTransition(() => {
          setTheme(newTheme)
        })
        .ready.then(() => {
          const clipPath = [
            `circle(0px at ${x}px ${y}px)`,
            `circle(${endRadius}px at ${x}px ${y}px)`,
          ]

          document.documentElement.animate(
            {
              clipPath:
                currentTheme === 'dark' ? [...clipPath].reverse() : clipPath,
            },
            {
              duration: 400,
              easing: 'ease-in',
              fill: 'both',
              pseudoElement:
                currentTheme === 'dark'
                  ? '::view-transition-old(root)'
                  : '::view-transition-new(root)',
            },
          )
        })
        .catch((error) => {
          console.error('Theme transition failed:', error)
          setTheme(newTheme)
        })
    } catch (error) {
      console.error('Failed to start view transition:', error)
      setTheme(newTheme)
    }
  }

  function initThemeToggle() {
    const toggle = document.getElementById('theme-toggle')
    if (!toggle) return

    toggle.removeEventListener('click', handleToggleClick)
    toggle.addEventListener('click', handleToggleClick)
  }

  initThemeToggle()

  document.addEventListener('astro:after-swap', () => {
    const storedTheme = localStorage.getItem('theme') || 'light'
    setTheme(storedTheme)
    initThemeToggle()
  })
</script>
