"use client"

import type { JSX } from "react"

import { useEffect, useRef } from "react"

import Cookies from "js-cookie"

import { fetchClient } from "@shared/api"
import { useAppDispatch } from "@shared/hooks/useAppDispatch"
import { useAppSelector } from "@shared/hooks/useAppSelector"
import { ACCESS_TOKEN_COOKIE } from "@shared/lib/constants"
import { setUser } from "@shared/store/user"

const TOKEN_POLL_INTERVAL = 2000

export const UserSync = (): JSX.Element | null => {
	const dispatch = useAppDispatch()
	const user = useAppSelector((state) => state.user.user)
	const userRef = useRef(user)
	const lastTokenRef = useRef<string | undefined>(undefined)

	useEffect(() => {
		userRef.current = user
	}, [user])

	useEffect(() => {
		let isCancelled = false

		const syncUserWithToken = async (): Promise<void> => {
			if (typeof window === "undefined") return

			const token = Cookies.get(ACCESS_TOKEN_COOKIE)

			if (!token) {
				lastTokenRef.current = undefined
				if (userRef.current) {
					dispatch(setUser(null))
				}
				return
			}

			// Skip refetch when token is unchanged and user is already cached
			if (lastTokenRef.current === token && userRef.current) return

			lastTokenRef.current = token

			try {
				const response = await fetchClient.GET("/api/users/me/")
				if (isCancelled) return

				if (response.data) {
					dispatch(setUser(response.data))
					return
				}
			} catch (error) {
				console.error("Failed to fetch current user:", error)
			}

			if (!isCancelled) {
				dispatch(setUser(null))
			}
		}

		syncUserWithToken()

		const intervalId = window.setInterval(
			syncUserWithToken,
			TOKEN_POLL_INTERVAL,
		)
		const handleFocus = (): void => {
			syncUserWithToken()
		}

		window.addEventListener("focus", handleFocus)

		return () => {
			isCancelled = true
			window.clearInterval(intervalId)
			window.removeEventListener("focus", handleFocus)
		}
	}, [dispatch])

	return null
}
