// api-client.jsx — Client JS qui parle au backend PHP

const API_BASE = (() => {
  // En dev local : pas d'API, mode démo (détecté par l'absence de TLD)
  var h = location.hostname;
  var isDevHost = !h.includes('.') || h === '127.0.0.1' || h.startsWith('192.168.') || h.startsWith('10.');
  if (isDevHost) return null;
  return location.pathname.includes('/app/') ? '/app/api' : '/api';
})();

// === Token storage ===
const TOKEN_KEY = 'trusta_token';
const USER_KEY = 'trusta_user';

const Auth = {
  getToken: () => { try { return localStorage.getItem(TOKEN_KEY); } catch (e) { return null; } },
  setToken: (t) => { try { localStorage.setItem(TOKEN_KEY, t); } catch (e) {} },
  clearToken: () => { try { localStorage.removeItem(TOKEN_KEY); localStorage.removeItem(USER_KEY); } catch (e) {} },
  getUser: () => { try { return JSON.parse(localStorage.getItem(USER_KEY) || 'null'); } catch (e) { return null; } },
  setUser: (u) => { try { localStorage.setItem(USER_KEY, JSON.stringify(u)); } catch (e) {} },
  isLoggedIn: () => !!localStorage.getItem(TOKEN_KEY),
};

window.TrustaAuth = Auth;

// === Fetch helper avec gestion auth + erreurs ===
async function apiFetch(path, options = {}) {
  if (!API_BASE) {
    throw new Error('API not available in dev mode');
  }
  const url = API_BASE + path;
  const headers = options.headers || {};
  const token = Auth.getToken();
  if (token) headers['Authorization'] = 'Bearer ' + token;

  // Envoie la langue de l'interface au backend pour les contenus auto-traduits (annonces, etc.)
  try {
    var lang = localStorage.getItem('trusta_lang') || 'ka';
    if (lang === 'ka' || lang === 'fr') headers['X-Lang'] = lang;
  } catch (e) {}

  // Auto JSON content-type pour body objet
  if (options.body && !(options.body instanceof FormData) && typeof options.body === 'object') {
    headers['Content-Type'] = 'application/json';
    options.body = JSON.stringify(options.body);
  }

  let res;
  try {
    res = await fetch(url, { ...options, headers });
  } catch (e) {
    throw { code: 'network_error', message: 'Connexion impossible' };
  }

  let data;
  try { data = await res.json(); } catch (e) { data = {}; }

  if (!res.ok) {
    if (res.status === 401) {
      Auth.clearToken();
    }
    throw {
      code: data.error || 'http_error',
      message: data.message || `HTTP ${res.status}`,
      status: res.status,
    };
  }
  return data;
}

// === API methods ===
window.TrustaAPI = {
  // Auth
  requestOtp: (phone, locale) =>
    apiFetch('/auth/request-otp.php', { method: 'POST', body: { phone, locale } }),

  verifyOtp: (phone, code) =>
    apiFetch('/auth/verify-otp.php', { method: 'POST', body: { phone, code } })
      .then(r => {
        if (r.token) {
          Auth.setToken(r.token);
          if (r.user) Auth.setUser(r.user);
        }
        return r;
      }),

  logout: () =>
    apiFetch('/auth/logout.php', { method: 'POST' })
      .finally(() => Auth.clearToken()),

  // Profil
  getMe: () => apiFetch('/me.php').then(r => { if (r.user) Auth.setUser(r.user); return r.user; }),

  updateMe: (updates) =>
    apiFetch('/me.php', { method: 'POST', body: updates })
      .then(r => { if (r.user) Auth.setUser(r.user); return r.user; }),

  uploadProfilePhoto: (file) => {
    const fd = new FormData();
    fd.append('photo', file);
    return apiFetch('/me-photo.php', { method: 'POST', body: fd });
  },

  // Listings
  listListings: (filters = {}) => {
    const qs = new URLSearchParams(Object.entries(filters).filter(([_, v]) => v !== '' && v != null)).toString();
    return apiFetch('/listings/index.php' + (qs ? '?' + qs : ''))
      .then(r => r.listings);
  },

  getListing: (id) => apiFetch(`/listings/show.php?id=${id}`).then(r => r.listing),

  createListing: (data) =>
    apiFetch('/listings/index.php', { method: 'POST', body: data }).then(r => r.listing),

  updateListing: (id, data) =>
    apiFetch(`/listings/show.php?id=${id}`, { method: 'PUT', body: data }).then(r => r.listing),

  deleteListing: (id) =>
    apiFetch(`/listings/show.php?id=${id}`, { method: 'DELETE' }),

  uploadListingPhoto: (file, listingId = null) => {
    const fd = new FormData();
    fd.append('photo', file);
    const path = '/listings/photos.php' + (listingId ? `?listing_id=${listingId}` : '');
    return apiFetch(path, { method: 'POST', body: fd });
  },

  // === Chat ===
  listConversations: () =>
    apiFetch('/chat/conversations.php').then(r => r.conversations),

  openConversation: (peerId, listingId = null) =>
    apiFetch('/chat/conversations.php', {
      method: 'POST',
      body: { peer_id: peerId, listing_id: listingId },
    }).then(r => r.conversation),

  listMessages: (conversationId, sinceId = 0) => {
    const qs = `?conversation_id=${conversationId}` + (sinceId ? `&since_id=${sinceId}` : '');
    return apiFetch('/chat/messages.php' + qs).then(r => r.messages);
  },

  sendMessage: (conversationId, body, photoUrl = null) =>
    apiFetch('/chat/messages.php', {
      method: 'POST',
      body: { conversation_id: conversationId, body, photo_url: photoUrl },
    }).then(r => r.message),

  // === Favoris ===
  listFavorites: (kind) =>
    apiFetch(`/favorites/index.php?kind=${kind}`).then(r => r.favorites),

  fetchFavoriteIds: () =>
    apiFetch('/favorites/index.php?ids=1').then(r => r.ids),

  toggleFavorite: (kind, targetId) =>
    apiFetch('/favorites/index.php', {
      method: 'POST',
      body: { kind, target_id: targetId },
    }).then(r => r.favorited),

  // === Notifications ===
  listNotifications: () =>
    apiFetch('/notifications/index.php').then(r => ({ items: r.notifications, unread: r.unread })),

  unreadCount: () =>
    apiFetch('/notifications/index.php?count=1').then(r => r.unread),

  markNotificationRead: (id) =>
    apiFetch('/notifications/index.php', { method: 'POST', body: { id } }),

  markAllNotificationsRead: () =>
    apiFetch('/notifications/index.php', { method: 'POST', body: { all: true } }),
};

// === Store global notifications (badge unread synchronisé) ===
(function () {
  let unread = 0;
  let pollId = null;
  const listeners = new Set();
  function notify() { listeners.forEach(fn => { try { fn(unread); } catch (e) {} }); }

  window.TrustaNotifStore = {
    getUnread() { return unread; },
    subscribe(fn) { listeners.add(fn); return () => listeners.delete(fn); },
    async refresh() {
      if (!window.API_AVAILABLE || !window.TrustaAuth || !window.TrustaAuth.isLoggedIn()) return;
      try {
        const n = await window.TrustaAPI.unreadCount();
        unread = Number(n) || 0;
        notify();
      } catch (e) { /* ignore */ }
    },
    startPolling(intervalMs = 30000) {
      if (pollId) return;
      this.refresh();
      pollId = setInterval(() => this.refresh(), intervalMs);
    },
    stopPolling() { if (pollId) { clearInterval(pollId); pollId = null; } },
  };
})();

// === Store global favoris (cache + listeners pour re-render multi-composants) ===
(function () {
  const state = { listing: new Set(), profile: new Set() };
  const listeners = new Set();
  function notify() { listeners.forEach(fn => { try { fn(); } catch (e) {} }); }

  window.TrustaFavStore = {
    isFav(kind, id) { return state[kind] && state[kind].has(Number(id)); },
    subscribe(fn) { listeners.add(fn); return () => listeners.delete(fn); },
    async refresh() {
      if (!window.API_AVAILABLE || !window.TrustaAuth || !window.TrustaAuth.isLoggedIn()) return;
      try {
        const ids = await window.TrustaAPI.fetchFavoriteIds();
        state.listing = new Set((ids.listing || []).map(Number));
        state.profile = new Set((ids.profile || []).map(Number));
        notify();
      } catch (e) { /* ignore */ }
    },
    async toggle(kind, id) {
      const numId = Number(id);
      // Optimistic
      const had = state[kind].has(numId);
      if (had) state[kind].delete(numId); else state[kind].add(numId);
      notify();
      try {
        const favorited = await window.TrustaAPI.toggleFavorite(kind, numId);
        // Reconcile au cas où le serveur a une autre vérité
        if (favorited) state[kind].add(numId); else state[kind].delete(numId);
        notify();
        return favorited;
      } catch (e) {
        // Rollback
        if (had) state[kind].add(numId); else state[kind].delete(numId);
        notify();
        throw e;
      }
    },
  };
})();

window.API_AVAILABLE = !!API_BASE;
