import { ref, computed, watch } from 'vue'
import { defineStore } from 'pinia'
import { useRoute, useRouter } from 'vue-router'
import { MemberState, myData } from '@shared/types/member'


const POLL_INTERVAL = 10_000

export const useUserStore = defineStore('user', () => {
    const user = ref<myData>(null)
    const roles = computed(() => new Set(user.value?.roles?.map(r => r.name) ?? []));
    const loaded = ref(false);
    const state = computed<MemberState | undefined>(() => user.value?.state || undefined);
    const isLoggedIn = computed(() => user.value !== null)
    const displayName = computed(() => user.value?.member.displayName || user.value?.member.member_name)

    async function loadUser() {
        //@ts-ignore
        const res = await fetch(`${import.meta.env.VITE_APIHOST}/members/me`, {
            credentials: 'include',
        });

        if (res.ok) {
            const data = await res.json();
            user.value = data;
        }

        loaded.value = true;
    }


    function hasRole(role: string): boolean {
        return roles.value.has(role)
    }


    function hasAnyRole(requiredRoles: string[]): boolean {
        return requiredRoles.some(r => roles.value.has(r))
    }

    //watcher to kick you off a page if your perms are revoked
    const route = useRoute();
    const router = useRouter();
    watch(user, (newUser) => {
        if (!newUser) return

        const currentRoute = route.meta

        // Member-only route
        if (currentRoute.memberOnly && state.value !== MemberState.Member) {
            router.replace('/unauthorized')
            return
        }

        // Role-based route
        if (currentRoute.roles && !hasRole('Dev') && !hasAnyRole(currentRoute.roles as string[])) {
            return '/unauthorized'
        }
    },
        { deep: true } // deep watch ensures nested changes trigger
    )

    //polling system
    let pollTimeout: number | null = null
    let polling = false;
    let lastVersion: string | null = null

    async function poll() {
        // Only poll if tab is visible
        if (document.hidden) {
            polling = false;
            return
        }

        await loadUser();

        scheduleNext()
    }

    function scheduleNext() {
        polling = true;
        pollTimeout = window.setTimeout(poll, POLL_INTERVAL)
    }

    poll() //start polling

    document.addEventListener('visibilitychange', () => {
        if (!document.hidden && polling === false) {
            poll()
        }
    })

    return { user, displayName, isLoggedIn, roles, loadUser, loaded, hasAnyRole, hasRole, state }
})
