import { defineStore } from "pinia"
import router from "#app/plugins/router";
import {Preferences} from "@capacitor/preferences";

export const useAuthStore = defineStore("auth", {
    state: () => ({
        user: null as null | {
            id?: string;
            user_id?: string;
            email: string;
            tenant_id?: string;
            role?: string;
            must_change_password?: boolean;
            is_admin?: boolean;
        },
        profile: null as null | any,
        tenants: [] as { tenant_id: string; role: string; tenants: { id: string; name: string }; id?: string; name?: string; hasActiveLicense?: boolean; locked?: string | null }[],
        permissions: [] as string[],
        activeTenant: null as any,
        activeTenantData: null as any,
        loading: true as boolean,
        notLoggedIn: true,
        sessionWarningVisible: false,
        sessionWarningRemainingSeconds: 0,
        sessionWarningLeadMs: 5 * 60 * 1000,
        sessionWarningTimer: null as ReturnType<typeof setTimeout> | null,
        sessionLogoutTimer: null as ReturnType<typeof setTimeout> | null,
        sessionCountdownTimer: null as ReturnType<typeof setInterval> | null,
    }),

    actions: {
        decodeTokenExpiryMs(token: string) {
            try {
                const parts = token.split(".")
                if (parts.length < 2) return null

                const payload = JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")))
                if (!payload?.exp) return null

                return Number(payload.exp) * 1000
            } catch (err) {
                console.error("Could not decode token expiry", err)
                return null
            }
        },

        clearSessionTimers() {
            if (!process.client) return

            if (this.sessionWarningTimer) {
                clearTimeout(this.sessionWarningTimer)
                this.sessionWarningTimer = null
            }

            if (this.sessionLogoutTimer) {
                clearTimeout(this.sessionLogoutTimer)
                this.sessionLogoutTimer = null
            }

            if (this.sessionCountdownTimer) {
                clearInterval(this.sessionCountdownTimer)
                this.sessionCountdownTimer = null
            }
        },

        startSessionCountdown(expiresAtMs: number) {
            if (!process.client) return

            if (this.sessionCountdownTimer) {
                clearInterval(this.sessionCountdownTimer)
            }

            this.sessionCountdownTimer = setInterval(() => {
                const remaining = Math.max(0, Math.ceil((expiresAtMs - Date.now()) / 1000))
                this.sessionWarningRemainingSeconds = remaining

                if (remaining <= 0 && this.sessionCountdownTimer) {
                    clearInterval(this.sessionCountdownTimer)
                    this.sessionCountdownTimer = null
                }
            }, 1000)
        },

        openSessionWarning(expiresAtMs: number) {
            this.sessionWarningVisible = true
            this.sessionWarningRemainingSeconds = Math.max(0, Math.ceil((expiresAtMs - Date.now()) / 1000))
            this.startSessionCountdown(expiresAtMs)
        },

        scheduleSessionTimers(token?: string | null) {
            if (!process.client) return

            const tokenToUse = token || useCookie("token").value

            this.clearSessionTimers()
            this.sessionWarningVisible = false
            this.sessionWarningRemainingSeconds = 0

            if (!tokenToUse) return

            const expiresAtMs = this.decodeTokenExpiryMs(tokenToUse)
            if (!expiresAtMs) return

            const now = Date.now()
            const msUntilLogout = expiresAtMs - now

            if (msUntilLogout <= 0) {
                void this.logout()
                return
            }

            this.sessionLogoutTimer = setTimeout(() => {
                this.sessionWarningVisible = false
                void this.logout()
            }, msUntilLogout)

            const msUntilWarning = msUntilLogout - this.sessionWarningLeadMs

            if (msUntilWarning <= 0) {
                this.openSessionWarning(expiresAtMs)
                return
            }

            this.sessionWarningTimer = setTimeout(() => {
                this.openSessionWarning(expiresAtMs)
            }, msUntilWarning)
        },

        setToken(token: string | null) {
            useCookie("token").value = token

            if (!token) {
                this.clearSessionTimers()
                this.sessionWarningVisible = false
                this.sessionWarningRemainingSeconds = 0
                return
            }

            this.scheduleSessionTimers(token)
        },

        async persist(token: string | null) {

            console.log("On Web")
            this.setToken(token)

        },

        async initStore() {
            console.log("Auth initStore")

            // 1. Check: Haben wir überhaupt ein Token?
            const token = useCookie("token").value

            /*if (!token) {
                // Kein Token -> Wir sind fertig, User ist Gast.
                this.user = null
                this.loading = false
                return
            }*/

            // 2. Token existiert -> Versuche User zu laden
            await this.fetchMe(token)

            // Wenn fetchMe fertig ist (egal ob Erfolg oder Fehler), ladebalken weg


            // Optional: Wenn eingeloggt, leite zur Home, falls gewünscht
            if(this.activeTenant > 0) {
                this.loading = false
                // Hier vorsichtig sein: Nicht navigieren, wenn der User auf eine Deep-Link URL will!
                // navigateTo("/")  <-- Das würde ich hier evtl. sogar weglassen und der Middleware überlassen
            }
        },

        async init(token=null) {
            console.log("Auth init")
            await this.fetchMe(token)

            const tempStore = useTempStore()

            if(this.profile?.temp_config) tempStore.setStoredTempConfig(this.profile.temp_config)
            if(this.activeTenant > 0) {
                this.loading = false

                navigateTo("/")
            }
        },

        async login(email: string, password: string) {
            try {
                console.log("Auth login")
                const { token } = await useNuxtApp().$api("/auth/login", {
                    method: "POST",
                    body: { email, password }
                })

                console.log("Token: " + token)

                // 1. WICHTIG: Token sofort ins Cookie schreiben, damit es persistiert wird
                this.setToken(token)

                // 2. User Daten laden
                await this.fetchMe(token)

                console.log(this.user)

                // 3. WICHTIG: Jetzt explizit weiterleiten!
                // Prüfen, ob der User geladen wurde
                if (this.user) {
                    // Falls Passwort-Änderung erzwungen wird (passend zu deiner Middleware)
                    if (this.user.must_change_password) {
                        return navigateTo("/password-change")
                    }

                    // Normaler Login -> Dashboard
                    return navigateTo("/")
                }

            } catch (e) {
                console.log("login error:" + e)
                // Hier könnte man noch eine Fehlermeldung im UI anzeigen
            }
        },

        async logout() {
            console.log("Auth logout")
            try {
                await useNuxtApp().$api("/auth/logout", { method: "POST" })
            } catch (e) {
                console.error("Logout API fehlgeschlagen (egal):", e)
            }

            // State resetten
            this.resetState()

            // Token löschen
            this.setToken(null)

            // Nur beim expliziten Logout navigieren wir
            navigateTo("/login")
        },

        resetState() {
            this.clearSessionTimers()
            this.user = null
            this.permissions = []
            this.profile = null
            this.activeTenant = null
            this.tenants = []
            this.activeTenantData = null
            this.sessionWarningVisible = false
            this.sessionWarningRemainingSeconds = 0
        },

        async fetchMe(jwt= null) {
            console.log("Auth fetchMe")
            const tempStore = useTempStore()

            // Token aus Argument oder Cookie holen
            const tokenToUse = jwt || useCookie("token").value

            try {
                const me = await useNuxtApp().$api("/api/me", {
                    headers: {
                        Authorization: `Bearer ${tokenToUse}`,
                        context: { jwt: tokenToUse }
                    }
                })

                // ... (Deine Logik für tenants, sorting etc. bleibt gleich) ...
                console.log(me)
                this.user = me.user
                this.permissions = me.permissions
                this.tenants = me.tenants

                this.tenants.sort(function (a, b) {
                    if (a.id < b.id)  return -1
                    if (a.id > b.id)  return 1
                })

                this.profile = me.profile

                if(this.profile?.temp_config) tempStore.setStoredTempConfig(this.profile.temp_config)

                if(me.activeTenant > 0) {
                    this.activeTenant = me.activeTenant
                    this.activeTenantData = me.tenants.find(i => i.id === me.activeTenant)
                }

                this.scheduleSessionTimers(tokenToUse)

                console.log(this)

            } catch (err: any) {
                // WICHTIG: Hier NICHT this.logout() aufrufen, weil das navigiert!
                console.log("fetchMe failed (Invalid Token or Network)", err)

                // Stattdessen nur den State sauber machen und Token löschen
                this.resetState()
                this.setToken(null)

                // Wir werfen den Fehler nicht weiter, damit initStore normal durchläuft
            }
        },

        async refreshSession() {
            try {
                const { token } = await useNuxtApp().$api("/api/auth/refresh", {
                    method: "POST",
                })

                this.setToken(token)
                await this.fetchMe(token)
                this.sessionWarningVisible = false
            } catch (err) {
                console.error("JWT refresh failed", err)
                await this.logout()
            }
        },

        async switchTenant(tenant_id: string) {
            console.log("Auth switchTenant")
            this.loading = true
            const res = await useNuxtApp().$api("/api/tenant/switch", {
                method: "POST",
                body: { tenant_id }
            })
            console.log(res)

            const {token} = res


            this.setToken(token)


            await this.init(token)
        },

        hasPermission(key: string) {
            return this.permissions.includes(key)
        }
    }
})
