import { useEffect } from "react"
import { useTranslation } from "react-i18next"
import { useMountEffect } from "@react-hookz/web"
import { gql, useQuery } from "~/generated/graphql"
import { getTabFileIds, useDispatch, useSelector } from "./store"
import { useDarkMode } from "~/shared/hooks/useDarkMode"
import { useOpenFile } from "./hooks/useOpenFile"
import { sideEffects } from "~/shared/sideEffect"
import { closeFile } from "./store/actions"
import { Theme } from "~/shared/models/enums.generated"
import { useActiveFileName } from "./hooks/useFileName"

export default sideEffects([
  function OpenFromURL() {
    const openFile = useOpenFile()
    useMountEffect(async () => {
      const open = new URL(location.href).searchParams.get("open")
      if (open) {
        try {
          await openFile(open)
        } finally {
          history.replaceState(null, "", location.pathname)
        }
      }
    })
  },

  function DarkModeClassName() {
    const darkMode = useDarkMode()

    useEffect(() => {
      document.body.classList.toggle("dark", darkMode)
      document.body.classList.toggle("light", !darkMode)
    }, [darkMode])
  },

  function ThemeProvider() {
    const darkMode = useDarkMode()
    const prefs = useQuery(ThemeQuery, {
      fetchPolicy: "cache-first",
    }).data?.preferences
    let theme = prefs?.theme
    if (!theme || theme === Theme.System) {
      theme = darkMode ? Theme.Dark : Theme.Light
    }

    const tokens = prefs
      ? theme === Theme.Light
        ? prefs?.lightTheme
        : prefs?.darkTheme
      : undefined

    useEffect(() => {
      if (tokens) {
        document.documentElement.dataset.theme = tokens
      }
    }, [tokens])
  },

  function Title() {
    const isUnsaved = useSelector(state => state.dirtyFileIds.has(state.activeFileId!))
    const fileTitle = useActiveFileName()

    if (fileTitle == null) {
      document.title = process.env.NEXT_PUBLIC_NAME!
      return
    }

    document.title = isUnsaved ? `* ${fileTitle}` : `${fileTitle}`
  },

  function Language() {
    const { i18n } = useTranslation()

    useEffect(() => {
      document.documentElement.lang = i18n.language
    }, [i18n.language])
  },

  function SyncState() {
    const dispatch = useDispatch()
    const tabs = useSelector(getTabFileIds)
    const { data: { files } = {} } = useQuery(SyncStateQuery, {
      fetchPolicy: "network-only",
      pollInterval: 3000,
    })

    useEffect(() => {
      if (!files) return

      const fileIds = new Set(files.map(s => s.id))
      for (const id of tabs.filter(t => !fileIds.has(t))) {
        dispatch(closeFile(id))
      }
    }, [tabs, dispatch, files])
  },
])

export const ThemeQuery = gql<"ThemeQuery">`
  query ThemeQuery {
    preferences {
      theme
      lightTheme
      darkTheme
    }
  }
`

const SyncStateQuery = gql<"SyncStateQuery">`
  query SyncStateQuery {
    files {
      id
    }
  }
`
