import { LocalStorage, SessionStorage } from 'quasar';
import { FG_Plugin } from '@flaschengeist/types';
import { fixSession, useSessionStore, useUserStore } from '.';
import { AxiosResponse } from 'axios';
import { api } from '../internal';
import { defineStore } from 'pinia';

function loadCurrentSession() {
  const session = LocalStorage.getItem<FG.Session>('session');
  if (session) session.expires = new Date(session.expires);
  return session || undefined;
}

function loadUser() {
  const user = SessionStorage.getItem<FG.User>('user');
  if (user && user.birthday) user.birthday = new Date(user.birthday);
  return user || undefined;
}

export const useMainStore = defineStore({
  id: 'main',

  state: () => ({
    session: loadCurrentSession(),
    user: loadUser(),
    notifications: [] as Array<FG_Plugin.Notification>,
    shortcuts: [] as Array<FG_Plugin.MenuLink>,
  }),

  getters: {
    loggedIn(): boolean {
      return this.session !== undefined;
    },
    currentUser(): FG.User {
      if (this.user === undefined) throw 'Not logged in, this should not be called';
      return this.user;
    },
    permissions(): string[] {
      return this.user?.permissions || [];
    },
  },

  actions: {
    /** Ininitalize store from saved session
     *  Updates session and loads current user
     */
    async init() {
      if (this.session) {
        const sessionStore = useSessionStore();
        const session = await sessionStore.getSession(this.session.token);
        if (session) {
          this.session = session;
          const userStore = useUserStore();
          const user = await userStore.getUser(this.session.userid);
          if (user) {
            this.user = user;
            SessionStorage.set('user', user);
          }
        }
      }
    },

    async login(userid: string, password: string) {
      try {
        const { data } = await api.post<FG.Session>('/auth', { userid, password });
        this.session = fixSession(data);
        return true;
      } catch ({ response }) {
        return (<AxiosResponse | undefined>response)?.status || false;
      }
    },

    async logout() {
      if (!this.session || !this.session.token) return false;

      try {
        const token = this.session.token;
        await api.delete(`/auth/${token}`);
      } catch (error) {
        return false;
      } finally {
        this.handleLoggedOut();
      }
      return true;
    },

    async requestReset(userid: string) {
      return await api
        .post('/auth/reset', { userid })
        .then(() => true)
        .catch(() => false);
    },

    async resetPassword(token: string, password: string) {
      return await api
        .post('/auth/reset', { token, password })
        .then(() => true)
        .catch(({ response }) =>
          response && 'status' in response ? (<AxiosResponse>response).status : false
        );
    },

    async loadNotifications(flaschengeist: FG_Plugin.Flaschengeist) {
      const { data } = await api.get<FG.Notification[]>('/notifications', {
        params:
          this.notifications.length > 0
            ? { from: this.notifications[this.notifications.length - 1].time }
            : {},
      });

      const notes = [] as FG_Plugin.Notification[];
      data.forEach((n) => {
        n.time = new Date(n.time);
        const plugin = flaschengeist?.plugins.filter((p) => p.id === n.plugin)[0];
        if (!plugin) console.debug('Could not find a parser for this notification', n);
        else notes.push(plugin.notification(n));
      });
      this.notifications.push(...notes);
      return notes;
    },

    async removeNotification(id: number) {
      const idx = this.notifications.findIndex((n) => n.id === id);
      if (idx >= 0)
        try {
          this.notifications.splice(idx, 1);
          await api.delete(`/notifications/${id}`);
        } catch (error) {
          if (this.notifications.length > idx)
            this.notifications.splice(idx, this.notifications.length - idx - 1);
        }
    },

    async getShortcuts() {
      const { data } = await api.get<Array<FG_Plugin.MenuLink>>(
        `users/${this.currentUser.userid}/shortcuts`
      );
      this.shortcuts = data;
    },

    async setShortcuts() {
      await api.put(`users/${this.currentUser.userid}/shortcuts`, this.shortcuts);
    },
    handleLoggedOut() {
      LocalStorage.clear();

      this.$patch({
        session: undefined,
        user: undefined,
      });
      SessionStorage.clear();
    },
  },
});

export default () => useMainStore;