import { reactive } from 'vue'
import { toast } from '~/main'

export const ThemeMode = {
  SYSTEM: 'system',
  LIGHT: 'light',
  DARK: 'dark',
}

const THEME_KEY = 'theme-mode'

export const themeState = reactive({
  mode: ThemeMode.SYSTEM,
})

function apply(mode) {
  if (!import.meta.client) return
  const root = document.documentElement
  let newMode =
    mode === ThemeMode.SYSTEM
      ? window.matchMedia('(prefers-color-scheme: dark)').matches
        ? 'dark'
        : 'light'
      : mode
  if (root.dataset.theme === newMode) return
  root.dataset.theme = newMode

  // 更新 meta 标签
  const androidMeta = document.querySelector('meta[name="theme-color"]')
  const iosMeta = document.querySelector('meta[name="apple-mobile-web-app-status-bar-style"]')
  const themeColor = getComputedStyle(document.documentElement)
    .getPropertyValue('--background-color')
    .trim()
  const themeStatus = newMode === 'dark' ? 'black-translucent' : 'default'

  if (androidMeta) {
    androidMeta.content = themeColor
  } else {
    const newAndroidMeta = document.createElement('meta')
    newAndroidMeta.name = 'theme-color'
    newAndroidMeta.content = themeColor
    document.head.appendChild(newAndroidMeta)
  }

  if (iosMeta) {
    iosMeta.content = themeStatus
  } else {
    const newIosMeta = document.createElement('meta')
    newIosMeta.name = 'apple-mobile-web-app-status-bar-style'
    newIosMeta.content = themeStatus
    document.head.appendChild(newIosMeta)
  }
}

export function initTheme() {
  if (!import.meta.client) return
  const saved = localStorage.getItem(THEME_KEY)
  if (saved && Object.values(ThemeMode).includes(saved)) {
    themeState.mode = saved
  }
  apply(themeState.mode)
}

export function setTheme(mode) {
  if (!import.meta.client) return
  if (!Object.values(ThemeMode).includes(mode)) return
  themeState.mode = mode
  localStorage.setItem(THEME_KEY, mode)
  apply(mode)
}

function getCircle(event) {
  if (!import.meta.client) return undefined

  let x, y
  if (event.touches?.length) {
    x = event.touches[0].clientX
    y = event.touches[0].clientY
  } else if (event.changedTouches?.length) {
    x = event.changedTouches[0].clientX
    y = event.changedTouches[0].clientY
  } else {
    x = event.clientX
    y = event.clientY
  }

  return {
    x,
    y,
    radius: Math.hypot(Math.max(x, window.innerWidth - x), Math.max(y, window.innerHeight - y)),
  }
}

function withViewTransition(event, applyFn, direction = true) {
  if (typeof document !== 'undefined' && document.startViewTransition) {
    const transition = document.startViewTransition(async () => {
      applyFn()
      await nextTick()
    })

    transition.ready
      .then(() => {
        const { x, y, radius } = getCircle(event)

        const clipPath = [`circle(0 at ${x}px ${y}px)`, `circle(${radius}px at ${x}px ${y}px)`]

        document.documentElement.animate(
          {
            clipPath: direction ? clipPath : [...clipPath].reverse(),
          },
          {
            duration: 400,
            easing: 'ease-in-out',
            pseudoElement: direction
              ? '::view-transition-new(root)'
              : '::view-transition-old(root)',
          },
        )
      })
      .catch(console.warn)
  } else {
    fallbackThemeTransition(applyFn)
  }
}

function fallbackThemeTransition(applyFn) {
  if (!import.meta.client) return

  const root = document.documentElement
  const computedStyle = getComputedStyle(root)

  // 获取当前背景色用于过渡
  const currentBg = computedStyle.getPropertyValue('--background-color').trim()

  // 创建过渡元素
  const transitionElement = document.createElement('div')
  transitionElement.style.cssText = `
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: ${currentBg};
    z-index: 9999;
    pointer-events: none;
    backdrop-filter: var(--blur-1);
  `
  document.body.appendChild(transitionElement)

  // 使用 Web Animations API 实现淡出动画
  const animation = transitionElement.animate([{ opacity: 1 }, { opacity: 0 }], {
    duration: 300,
    easing: 'ease-out',
  })

  // 应用主题变更
  applyFn()

  // 动画完成后清理
  animation.finished
    .then(() => {
      document.body.removeChild(transitionElement)
    })
    .catch(() => {
      // 降级处理
      document.body.removeChild(transitionElement)
    })
}

function getSystemTheme() {
  return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}

export function cycleTheme(event) {
  if (!import.meta.client) return
  const modes = [ThemeMode.SYSTEM, ThemeMode.LIGHT, ThemeMode.DARK]
  const index = modes.indexOf(themeState.mode)
  const next = modes[(index + 1) % modes.length]
  if (next === ThemeMode.SYSTEM) {
    toast.success('💻 已经切换到系统主题')
  } else if (next === ThemeMode.LIGHT) {
    toast.success('🌞 已经切换到明亮主题')
  } else {
    toast.success('🌙 已经切换到暗色主题')
  }
  // 获取当前真实主题
  const currentTheme = themeState.mode === ThemeMode.SYSTEM ? getSystemTheme() : themeState.mode

  // 获取新主题的真实表现
  const nextTheme = next === ThemeMode.SYSTEM ? getSystemTheme() : next

  // 如果新旧主题相同，不用过渡动画
  if (currentTheme === nextTheme) {
    setTheme(next)
    return
  }

  // 计算新主题是否是暗色
  const newThemeIsDark = nextTheme === 'dark'

  withViewTransition(
    event,
    () => {
      setTheme(next)
    },
    !newThemeIsDark,
  )
}

if (import.meta.client && window.matchMedia) {
  window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
    if (themeState.mode === ThemeMode.SYSTEM) {
      apply(ThemeMode.SYSTEM)
    }
  })
}
