// The Lucia project.
// Copyright 2023-2026 DSP, inc.  All rights reserved.
// Authors:
//   chiayin.kuo@dsp.im (chiayin), 2023/1/31
//   imacat.yang@dsp.im (imacat), 2023/9/23
//   cindy.chang@dsp.im (Cindy Chang), 2024/5/30
/**
 * @module stores/login Authentication store for login, logout,
 *   token management, and user data.
 */

import { defineStore } from "pinia";
import axios from "axios";
import apiClient from "@/api/client.js";
import apiError from "@/module/apiError.js";
import { decodeReturnTo } from "@/utils/returnToEncoding";
import {
  deleteCookie,
  setCookie,
  setCookieWithoutExpiration,
} from "../utils/cookieUtil";

/** Pinia store for authentication and user session management. */
export const useLoginStore = defineStore("loginStore", {
  // data, methods, computed
  // state, actions, getters
  state: () => ({
    auth: {
      grant_type: "password", // password | refresh_token
      username: "",
      password: "",
      refresh_token: undefined,
    },
    isInvalid: false,
    userData: {},
    isLoggedIn: false,
    rememberedReturnToUrl: "",
  }),
  actions: {
    /**
     * fetch Login For Access Token api
     */
    async signIn() {
      const api = "/api/oauth/token";
      const config = {
        headers: {
          // Default URL-encoded format for HTTP POST, not JSON
          "Content-Type": "application/x-www-form-urlencoded",
        },
      };

      try {
        const response = await axios.post(api, this.auth, config);
        const accessToken = response.data.access_token;
        const refresh_token = response.data.refresh_token;
        // Store the token in a cookie
        setCookieWithoutExpiration("luciaToken", accessToken);
        const expiryDate = new Date();
        expiryDate.setMonth(expiryDate.getMonth() + 6);
        setCookie(
          "luciaRefreshToken",
          refresh_token,
          Math.ceil(
            (expiryDate.getTime() - Date.now()) / (24 * 60 * 60 * 1000),
          ),
        );

        this.isLoggedIn = true;
        setCookie("isLuciaLoggedIn", "true");

        // By default, redirect to the FILES page.
        // However, if the user pasted a URL while not logged in,
        // redirect them to the remembered return-to URL after login.
        if (this.rememberedReturnToUrl !== "") {
          let decodedUrl = "";
          try {
            decodedUrl = decodeReturnTo(this.rememberedReturnToUrl);
          } catch {
            this.$router.push("/files");
            return;
          }
          // Only allow relative paths to prevent open redirect attacks
          if (decodedUrl.startsWith("/") && !decodedUrl.startsWith("//")) {
            globalThis.location.href = decodedUrl;
            return;
          }
        }
        this.$router.push("/files");
      } catch (error) {
        console.error("Login failed:", error);
        this.isInvalid = true;
      }
    },
    /**
     * Refresh Token
     */
    async refreshToken() {
      const { refreshTokenAndGetNew } = await import("@/api/auth.js");
      await refreshTokenAndGetNew();
    },
    /**
     * Logout, token expired
     */
    logOut() {
      deleteCookie("luciaToken");
      deleteCookie("luciaRefreshToken");

      this.isLoggedIn = false;
      deleteCookie("isLuciaLoggedIn");

      this.$router.push("/login");
    },
    /**
     * get user detail for 'my-account' api
     */
    async getUserData() {
      const api = "/api/my-account";

      try {
        const response = await apiClient.get(api);

        this.userData = response.data;
      } catch (error) {
        apiError(error, "Failed to load user data.");
      }
    },
    /**
     * check login for 'my-account' api
     */
    async checkLogin() {
      const api = "/api/my-account";

      try {
        await apiClient.get(api);
      } catch (error) {
        console.error("Session check failed:", error);
        this.$router.push("/login");
      }
    },
    setRememberedReturnToUrl(returnToUrl) {
      this.rememberedReturnToUrl = returnToUrl;
    },
    setIsLoggedIn(boolean) {
      this.isLoggedIn = boolean;
    },
  },
});
