import jwt_decode from 'jwt-decode';
import { User } from '@/lib/user';

async function login ({ commit, dispatch }, loginRequest) {
  const url = "/login";
  const init = {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: loginRequest
  };

  const callback = async (err, res) => {
    if (!err && res) {
      const { token } = (await res.json());
      await dispatch('setCredentials', {token});
    }
  }

  await dispatch('api', [url, init, callback]);
  await dispatch('loadUserPreferences');
}

async function logout ({ commit, dispatch }) {
  commit('setToken', null);
  commit('setUser', null);
  await dispatch('api', ["/logout"]);
  commit('setPreferences', {});
}

function setCredentials({ state, commit, getters, dispatch, rootState }, { force, token, response } = {}) {
  try {
    let tokenValue = token;

    if (!tokenValue && response?.headers?.get('x-jwt')) {
      tokenValue = response.headers.get('x-jwt');
    }

    if (!tokenValue) {
      console.log('No JWT found in token or response');
      return;
    }

    if (force || tokenValue !== getters.jwt) {
      const decoded = jwt_decode(tokenValue);
      commit('setToken', tokenValue);
      commit('setUser', decoded ? new User(decoded, rootState.api.api) : null);
      commit('setCookie', {name: "JWT", value: tokenValue, expires: (decoded.exp??0)*1000});

      console.log('Credentials refreshed at', new Date().toISOString());
    } else {
      console.log('JWT unchanged, skipping update');
    }
  } catch (err) {
    console.error('setCredentials error:', err.message, 'token:', token, 'response:', response?.headers?.get('x-jwt'));
    if (err.name === 'InvalidTokenError') {
      commit('setToken', null);
      commit('setUser', null);
      commit('clearCookie', "JWT")
    }
  }
  dispatch('loadUserPreferences');
}

function saveUserPreference({ state, commit }, [key, value]) {
  const k = `${state.user?.id}.${key}`;
  if (value !== undefined) {
    localStorage.setItem(k, JSON.stringify(value));
    const preferences = { ...state.preferences, [key]: value };
    commit('setPreferences', preferences);
  } else {
    localStorage.removeItem(k);
    const preferences = { ...state.preferences };
    delete preferences[key];
    commit('setPreferences', preferences);
  }
}

async function loadUserPreferences({ state, commit }) {
  const prefix = `${state.user?.id}`;
  const keys = Object.keys(localStorage).filter(k => k.startsWith(prefix));
  const preferences = {};
  keys.forEach(str => {
    const value = JSON.parse(localStorage.getItem(str));
    const key = str.split(".").slice(2).join(".");
    preferences[key] = value;
  });
  commit('setPreferences', preferences);
}

export default {
  login,
  logout,
  setCredentials,
  saveUserPreference,
  loadUserPreferences
};
