import { defineStore } from "pinia";
import { apiRequest } from "../data/api";
import { closeUserDb } from "../data/db";

export type SessionUser = { id: string; name: string };

let sessionPromise: Promise<void> | null = null;
const LAST_SESSION_KEY = "cents:last-session-user";

function readLastSession(): SessionUser | null {
  try {
    const value = localStorage.getItem(LAST_SESSION_KEY);
    if (!value) return null;
    const user = JSON.parse(value) as SessionUser;
    return user?.id && user?.name ? user : null;
  } catch {
    return null;
  }
}

function writeLastSession(user: SessionUser | null) {
  try {
    if (user) localStorage.setItem(LAST_SESSION_KEY, JSON.stringify(user));
    else localStorage.removeItem(LAST_SESSION_KEY);
  } catch {
    // Storage can be disabled by the browser; server auth still works.
  }
}

export const useAuthStore = defineStore("auth", {
  state: () => ({
    user: null as SessionUser | null,
    loaded: false,
    unavailable: false,
  }),
  actions: {
    async loadSession(force = false) {
      if (this.loaded && !force) return;
      if (sessionPromise) return sessionPromise;
      sessionPromise = (async () => {
        try {
          const result = await apiRequest<{ user: SessionUser | null }>("/api/auth/session");
          this.user = result.user;
          this.unavailable = false;
          writeLastSession(result.user);
        } catch {
          this.user = readLastSession();
          this.unavailable = true;
        } finally {
          this.loaded = true;
        }
      })();
      try {
        await sessionPromise;
      } finally {
        sessionPromise = null;
      }
    },
    async updateName(name: string) {
      const result = await apiRequest<{ user: SessionUser }>("/api/me", {
        method: "PATCH",
        body: { name },
      });
      this.user = result.user;
      writeLastSession(result.user);
    },
    async login(name: string, password: string) {
      const result = await apiRequest<{ user: SessionUser }>("/api/auth/login", {
        method: "POST",
        body: { name, password },
      });
      this.user = result.user;
      this.loaded = true;
      this.unavailable = false;
      writeLastSession(result.user);
    },
    async logout() {
      const userId = this.user?.id;
      await apiRequest("/api/auth/logout", { method: "POST" });
      if (userId) closeUserDb(userId);
      this.user = null;
      this.loaded = true;
      writeLastSession(null);
    },
  },
});
