import { bustItGetCache, itGetCached, itPost } from "@/fetchHelpers";
import { setI18nLanguage } from "@/i18nextWrapper";
import type { Country } from "@/services/entities";
import { directUpload } from "@/services/files";
import dayjs from "dayjs";
import { defineStore } from "pinia";

let logoutRedirectUrl = import.meta.env.VITE_LOGOUT_REDIRECT || "/";

if (import.meta.env.VITE_OAUTH_API_BASE_URL) {
  logoutRedirectUrl = `${
    import.meta.env.VITE_OAUTH_API_BASE_URL
  }logout/?post_logout_redirect_uri=${window.location.origin}`;
}

const AVAILABLE_LANGUAGES = ["de", "fr", "it"];

export type AvailableLanguages = "de" | "fr" | "it";
export type InvoiceAddress = "prv" | "org";

export interface User {
  id: string;
  username: string;
  first_name: string;
  last_name: string;
  email: string;
  avatar_url: string;
  organisation: number | null;
  is_superuser: boolean;
  loggedIn: boolean;
  language: AvailableLanguages;
  course_session_experts: string[];
  invoice_address: InvoiceAddress | null;
  street: string | null;
  street_number: string | null;
  postal_code: string | null;
  city: string | null;
  country: Country | null;
  organisation_detail_name: string | null;
  organisation_street: string | null;
  organisation_street_number: string | null;
  organisation_postal_code: string | null;
  organisation_city: string | null;
  organisation_country: Country | null;
}

let defaultLanguage: AvailableLanguages = "de";

const isAvailableLanguage = (language: string): language is AvailableLanguages => {
  return AVAILABLE_LANGUAGES.includes(language);
};

const languagesWithoutCountryCode = navigator.languages.map(
  (lang) => lang.split("-")[0]
);

for (const language of languagesWithoutCountryCode) {
  if (isAvailableLanguage(language)) {
    defaultLanguage = language;
    break;
  }
}

const initialUserState: User = {
  id: "",
  email: "",
  first_name: "",
  last_name: "",
  username: "",
  avatar_url: "",
  is_superuser: false,
  organisation: 0,
  course_session_experts: [],
  loggedIn: false,
  language: defaultLanguage,
  invoice_address: "prv",
  street: null,
  street_number: null,
  postal_code: null,
  city: null,
  country: null,
  organisation_detail_name: null,
  organisation_street: null,
  organisation_street_number: null,
  organisation_postal_code: null,
  organisation_city: null,
  organisation_country: null,
};

async function setLocale(language: AvailableLanguages) {
  switch (language) {
    case "de":
      await import("dayjs/locale/de");
      break;
    case "fr":
      await import("dayjs/locale/fr");
      break;
    case "it":
      await import("dayjs/locale/it");
  }
  dayjs.locale(language);
  setI18nLanguage(language);
}

export const useUserStore = defineStore({
  id: "user",
  state: () => initialUserState as User,
  getters: {
    getFullName(): string {
      return `${this.first_name} ${this.last_name}`.trim();
    },
    languageName(): string {
      if (this.language === "de") {
        return "Deutsch";
      }
      if (this.language === "fr") {
        return "Français";
      }
      if (this.language === "it") {
        return "Italiano";
      }

      return this.language;
    },
  },
  actions: {
    async handleLogin(username: string, password: string, next = "/") {
      if (username && password) {
        try {
          this.$state = await itPost("/api/core/login/", {
            username,
            password,
          });
          this.loggedIn = true;
          bustItGetCache();
          window.location.href = next;
        } catch (e) {
          this.loggedIn = false;
          alert("Login failed");
        }
      }
    },
    handleLogout() {
      Object.assign(this, initialUserState);

      itPost("/api/core/logout/", {}).then(() => {
        let redirectUrl;

        if (logoutRedirectUrl !== "") {
          redirectUrl = logoutRedirectUrl;
        } else {
          redirectUrl = "/";
        }
        window.location.href = redirectUrl;
      });
    },
    async fetchUser() {
      const data = await itGetCached("/api/core/me/");
      this.$state = data;
      this.loggedIn = true;
      await setLocale(data.language);
    },
    async setUserAvatar(file: File) {
      const r = await directUpload("/api/core/avatar/", file);
      this.$state.avatar_url = r.url;
    },
    async updateUserProfile(profileData: Partial<User>) {
      if (profileData.language) {
        await setLocale(profileData.language);
      }

      await itPost("/api/core/me/", profileData, { method: "PUT" });
      Object.assign(this.$state, profileData);
    },
  },
});
