const STORAGE_KEY = 'esp32block_auth';

let current = null;
const listeners = new Set();

function load() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (!raw) return null;
    const parsed = JSON.parse(raw);
    if (!parsed?.token || !parsed?.user) return null;
    return parsed;
  } catch {
    return null;
  }
}

function persist(value) {
  current = value;
  if (value) {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(value));
  } else {
    localStorage.removeItem(STORAGE_KEY);
  }
  for (const fn of listeners) {
    try { fn(current); } catch { /* ignore */ }
  }
}

export function getAuth() {
  if (current !== null) return current;
  current = load();
  return current;
}

export function onAuthChange(fn) {
  listeners.add(fn);
  return () => listeners.delete(fn);
}

function apiUrl(path) {
  const base = import.meta.env.BASE_URL || '/';
  const p = path.startsWith('/') ? path.slice(1) : path;
  return (base.endsWith('/') ? base : base + '/') + p;
}

async function request(path, { method = 'GET', body, auth = false } = {}) {
  const headers = { 'Content-Type': 'application/json' };
  if (auth) {
    const a = getAuth();
    if (a?.token) headers['Authorization'] = `Bearer ${a.token}`;
  }
  const res = await fetch(apiUrl(path), {
    method,
    headers,
    body: body ? JSON.stringify(body) : undefined,
  });
  let data = null;
  try { data = await res.json(); } catch { /* non-json */ }
  if (!res.ok) {
    const msg = data?.error || `HTTP ${res.status}`;
    throw new Error(msg);
  }
  return data;
}

export async function login(username, password) {
  const data = await request('/api/auth/login', { method: 'POST', body: { username, password } });
  persist({ token: data.token, user: data.user });
  return data.user;
}

export async function register(username, password) {
  const data = await request('/api/auth/register', { method: 'POST', body: { username, password } });
  persist({ token: data.token, user: data.user });
  return data.user;
}

export async function logout() {
  try { await request('/api/auth/logout', { method: 'POST', auth: true }); } catch { /* ignore */ }
  persist(null);
}

export async function refreshMe() {
  const a = getAuth();
  if (!a?.token) return null;
  try {
    const data = await request('/api/auth/me', { auth: true });
    persist({ token: a.token, user: data.user });
    return data.user;
  } catch {
    persist(null);
    return null;
  }
}

export function getToken() {
  return getAuth()?.token || null;
}

export function getUser() {
  return getAuth()?.user || null;
}

export function isLoggedIn() {
  return !!getToken();
}
