/**
 * AuthService
 * Manages authentication tokens and user role detection via JWT decoding.
 *
 * Roles (from JWT claims):
 *   - Owner: roles array contains "Owner"
 *   - Customer: authenticated but no "Owner" role
 *   - Guest: no token
 *
 * Methods:
 *   addToken(token)       — store JWT token
 *   getToken()            — retrieve JWT token
 *   deleteToken()         — remove JWT token
 *   decodeToken()         — decode JWT payload
 *   getUser()             — get decoded user info
 *   getRoles()            — get roles array from JWT
 *   isOwner()             — check if user has Owner role
 *   isCustomer()          — check if user is authenticated but not Owner
 *   isGuest()             — check if no token exists
 *   isAuthenticated()     — check if token exists
 */

const TOKEN_KEY = 'auth_token';
const USER_KEY = 'cached_user';

const AuthService = Object.freeze({
  addToken(token) {
    if (!token || typeof token !== 'string') return;
    localStorage.setItem(TOKEN_KEY, token);
  },

  getToken() {
    return localStorage.getItem(TOKEN_KEY);
  },

  deleteToken() {
    localStorage.removeItem(TOKEN_KEY);
    localStorage.removeItem(USER_KEY);
  },

  /**
   * Cache full user profile (from API)
   * @param {object} user — { name, email, phone, ... }
   */
  cacheUser(user) {
    if (!user) return;
    localStorage.setItem(USER_KEY, JSON.stringify(user));
  },

  /**
   * Get cached user profile
   * @returns {object|null}
   */
  getCachedUser() {
    try {
      return JSON.parse(localStorage.getItem(USER_KEY));
    } catch {
      return null;
    }
  },

  /**
   * Decode JWT payload (base64)
   * @returns {object|null}
   */
  decodeToken() {
    const token = this.getToken();
    if (!token) return null;
    try {
      const payload = token.split('.')[1];
      return JSON.parse(atob(payload));
    } catch {
      return null;
    }
  },

  /**
   * Extract user info from JWT
   * @returns {object|null} — { id, name, email, phone, roles }
   */
  getUser() {
    const payload = this.decodeToken();
    if (!payload) return null;

    const cached = this.getCachedUser();

    return {
      id: payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier'] || payload.sub || null,
      name: cached?.name || payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name'] || null,
      email: cached?.email || payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'] || null,
      phone: cached?.phone || payload['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone'] || null,
      roles: this.getRoles(),
    };
  },

  /**
   * Get current authenticated user id
   * @returns {number|string|null}
   */
  getUserId() {
    const user = this.getUser();
    if (!user?.id) return null;

    const parsedId = Number(user.id);
    return Number.isFinite(parsedId) ? parsedId : user.id;
  },

  /**
   * Get roles array from JWT
   * @returns {string[]}
   */
  getRoles() {
    const payload = this.decodeToken();
    if (!payload) return [];
    const roles = payload['http://schemas.microsoft.com/ws/2008/06/identity/claims/role'];
    if (Array.isArray(roles)) return roles;
    if (typeof roles === 'string') return [roles];
    return [];
  },

  /**
   * User has Owner role
   * @returns {boolean}
   */
  isOwner() {
    return this.getRoles().includes('Owner');
  },

  /**
   * Authenticated user without Owner role (i.e. customer)
   * @returns {boolean}
   */
  isCustomer() {
    return this.isAuthenticated() && !this.isOwner();
  },

  /**
   * No token — guest user
   * @returns {boolean}
   */
  isGuest() {
    return !this.getToken();
  },

  /**
   * Token exists
   * @returns {boolean}
   */
  isAuthenticated() {
    return !!this.getToken();
  },
});

export default AuthService;

