import axios from "axios"
import { defineStore } from "pinia";
import { api } from "@/api"
import router from "@/router"
import { getLocalToken, removeLocalToken, saveLocalToken } from "@/utils";
import type { AppNotification } from '@/interfaces';
import type { IUserProfile, IUserProfileCreate, IUserProfileUpdate, MainState, Video} from '@/interfaces';
import i18n from '@/plugins/i18n'

const defaultState: MainState = {
  isLoggedIn: null,
  token: '',
  logInError: false,
  userProfile: null,
  dashboardMiniDrawer: false,
  dashboardShowDrawer: true,
  notifications: [],
  videos: [],
};

export const useMainStore = defineStore("MainStoreId", {
  state: () => defaultState,

  getters: {
    readhasAdminAccess: (state) =>
      state.userProfile && state.userProfile.is_superuser && state.userProfile.is_active,
    readLoginError: (state) => state.logInError,
    readDashboardShowDrawer: (state) => state.dashboardShowDrawer,
    readDashboardMiniDrawer: (state) => state.dashboardMiniDrawer,
    readUserProfile: (state) => state.userProfile,
    readToken: (state) => state.token,
    readIsLoggedIn: (state) => state.isLoggedIn,
    readFirstNotification: (state) => state.notifications.length > 0 && state.notifications[0],
    readVideos: (state) => state.videos,
  },

  actions: {
    // setters
    setToken(payload: string) { this.token = payload; },
    setLoggedIn(payload: boolean) { this.isLoggedIn = payload; },
    setLogInError(payload: boolean) { this.logInError = payload; },
    setUserProfile(payload: IUserProfile) { this.userProfile = payload },
    setDashboardMiniDrawer(payload: boolean) { this.dashboardMiniDrawer = payload; },
    setDashboardShowDrawer(payload: boolean) { this.dashboardShowDrawer = payload; },
    setVideos(payload: Video[]) { this.videos = payload },
    addNotification(payload: AppNotification) { this.notifications.push(payload); },
    removeNotification(payload: AppNotification) {
      if (payload) {
        this.notifications = this.notifications.filter(
          (notification) => notification !== payload,
        );
      }
    },
    // actions
    async logIn(username: string, password: string) {
      try {
        const response = await api.logInGetToken(username, password);
        const token: string = response.data.access_token;
        if (token) {
          saveLocalToken(token);
          this.setToken(token);
          this.setLoggedIn(true);
          this.setLogInError(false);
          await this.getUserProfile();
          await this.routeLoggedIn();
          this.addNotification({ content: i18n.global.t("loggedIn"), color: "success" });
        } else {
          await this.logOut();
        }
      } catch (err) {
        this.setLogInError(true);
        await this.logOut();
      }
    },
    async getUserProfile() {
      try {
        const response = await api.getMe(this.token);
        if (response.data) {
          this.setUserProfile(response.data)
        }
      } catch (error) {
        await this.checkApiError(error);
      }
    },
    async updateUserProfile(payload: IUserProfileUpdate) {
      try {
        const loadingNotification = { content: "saving", showProgress: true };
        await this.addNotification(loadingNotification);
        const response = (
          await Promise.all([
            api.updateMe(this.token, payload),
            await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 500)),
          ])
        )[0];
        this.setUserProfile(response.data);
        this.removeNotification(loadingNotification);
        this.addNotification({
          content: i18n.global.t("profileUpdated"),
          color: "success",
        });
      } catch (error) {
        await this.checkApiError(error);
      }
    },
    async checkLoggedIn() {
      if (!this.isLoggedIn) {
        let token = this.token;
        if (!token) {
          const localToken = getLocalToken();
          if (localToken) {
            this.setToken(localToken);
            token = localToken;
          }
        }
        if (token) {
          try {
            const response = await api.getMe(token);
            this.setLoggedIn(true);
            this.setUserProfile(response.data);
            router.push("/main/dashboard");
          } catch (error) {
            await this.removeLogIn();
          }
        } else {
          await this.removeLogIn();
        }
      }
    },
    async removeLogIn() {
      removeLocalToken();
      this.setToken("");
      this.setLoggedIn(false);
    },
    async logOut() {
      await this.removeLogIn();
      this.routeLogOut();
    },
    async userLogOut() {
      await this.logOut();
      this.addNotification({ content: "Logged out", color: "success" });
    },
    routeLogOut() {
      if (router.currentRoute.value.path !== "/login") {
        router.push("/login");
      }
    },
    async checkApiError(payload: unknown) {
      if (axios.isAxiosError(payload)) {
        if (payload.response?.status === 401) {
          await this.logOut();
        }
      }
    },
    routeLoggedIn() {
      if (router.currentRoute.value.path === "/login" || router.currentRoute.value.path === "/") {
        router.push("/main/dashboard");
      }
    },
    async dispatchRemoveNotification(payload: { notification: AppNotification; timeout: number },) {
      return new Promise((resolve, _) => {
        setTimeout(() => {
          this.removeNotification(payload.notification);
          resolve(true);
        }, payload.timeout);
      });
    },
    async register(payload: IUserProfileCreate) {
      const loadingNotification = {
        content: i18n.global.t("signingUp"),
        showProgress: true,
      };
      try {
        this.addNotification(loadingNotification);
        const response = (
          await Promise.all([
            api.registerUser(payload),
            await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 500)),
          ])
        )[0];
        this.removeNotification(loadingNotification);
        this.addNotification({
          content: i18n.global.t("registerSuccess"),
          color: "success",
        });
        setTimeout(() => {
          router.push("/login")
        }, 2000)
      } catch (error) {
        await this.checkApiError(error);
      }
    },
    async passwordRecovery(username: string ) {
        const loadingNotification = {
            content: "Sending password recovery email",
            showProgress: true,
        };
        try {
            this.addNotification(loadingNotification);
            await Promise.all([
              api.passwordRecovery(username),
              await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 500)),
            ]);
            this.removeNotification(loadingNotification);
            this.addNotification({
              content: "Password recovery email sent",
              color: "success",
            });
            await this.logOut();
        } catch (error) {
            this.removeNotification(loadingNotification);
            this.addNotification({ color: "error", content: "Incorrect username" });
        }
    },
    async resetPassword(password: string, token: string) {
        const loadingNotification = { content: "Resetting password", showProgress: true };
        try {
            this.addNotification(loadingNotification);
            await Promise.all([
                api.resetPassword(token, password),
                await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 500)),
            ]);
            this.removeNotification(loadingNotification);
            this.addNotification( {
                content: "Password successfully reset",
                color: "success",
            });
            await this.logOut();
        } catch (error) {
            this.removeNotification(loadingNotification);
            this.addNotification({
                color: "error",
                content: "Error resetting password",
            });
        }
    },
    async uploadPlot(title: string, file: File) {
      const mainStore = useMainStore();
      try {
        const loadingNotification = { content: "sending", showProgress: true };
        mainStore.addNotification(loadingNotification);
        const response = (
          await Promise.all([
            api.uploadPlot(mainStore.token, title, file),
            await new Promise<void>((resolve, _) => setTimeout(() => resolve(), 500)),
          ])
        );
        mainStore.removeNotification(loadingNotification);
        mainStore.addNotification({
          content: "File received",
            color: "success",
        })
      } catch (error) {
        await mainStore.checkApiError(error);
      }
    },
    async actionGetVideos() {
      const mainStore = useMainStore();
      try {
        const response = await api.getVideos(mainStore.token)
        if (response) {
          this.setVideos(response.data);
        }
      } catch (error) {
        await mainStore.checkApiError(error);
      }
    },
    }
});


