/**
 * Oveyo PWA — State management + API client + hooks personnalisés
 */

const API_BASE = '';
const STORAGE_KEY = 'oveyo:state:v2';

// ============================================================
// STATE PERSISTENT (localStorage)
// ============================================================
const defaultState = () => ({
  user: { phone: null, pseudonym: null, neighborhood_slug: null, language: 'fr', geolocation: null },
  persona: { ambassador_validated: false, merchant_validated: false },
  pwa: { install_dismissed: false, push_subscribed: false },
  ambassador_level: 'apprenti', // apprenti / confirmé / maître
});

const loadState = () => {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    return raw ? { ...defaultState(), ...JSON.parse(raw) } : defaultState();
  } catch {
    return defaultState();
  }
};

const saveState = (state) => {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
};

// ============================================================
// API CLIENT
// ============================================================
const api = async (endpoint, options = {}) => {
  const url = `${API_BASE}${endpoint}`;
  const opts = {
    headers: { 'Content-Type': 'application/json', ...(options.headers || {}) },
    ...options,
  };
  const response = await fetch(url, opts);
  if (!response.ok) {
    const err = new Error(`HTTP ${response.status}`);
    err.status = response.status;
    try { err.body = await response.json(); } catch {}
    throw err;
  }
  return response.json();
};

// ============================================================
// HOOK : usePrices (consultation des prix)
// ============================================================
const usePrices = (neighborhoodSlug = '', days = 7) => {
  const [data, setData] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    setLoading(true);
    setError(null);
    const params = new URLSearchParams({ days: String(days) });
    if (neighborhoodSlug) params.set('neighborhood_slug', neighborhoodSlug);
    api(`/api/pwa/prices?${params}`)
      .then((d) => { if (!cancelled) setData(d); })
      .catch((e) => { if (!cancelled) setError(e); })
      .finally(() => { if (!cancelled) setLoading(false); });
    return () => { cancelled = true; };
  }, [neighborhoodSlug, days]);

  return { data, loading, error };
};

// ============================================================
// HOOK : useCatalog (produits + quartiers, cache long)
// ============================================================
const useCatalog = () => {
  const [catalog, setCatalog] = React.useState({ products: [], neighborhoods: [] });
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    api('/api/pwa/catalog')
      .then((d) => setCatalog(d))
      .finally(() => setLoading(false));
  }, []);

  return { ...catalog, loading };
};

// ============================================================
// HOOK : usePharmaciesOnDuty
// ============================================================
const usePharmaciesOnDuty = () => {
  const [pharmacies, setPharmacies] = React.useState([]);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    api('/api/pwa/pharmacies/on-duty')
      .then((d) => setPharmacies(d.pharmacies || []))
      .catch(() => setPharmacies([]))
      .finally(() => setLoading(false));
  }, []);

  return { pharmacies, loading };
};

// ============================================================
// HOOK : useShops (boutiques pour un produit donné, filtrable)
// ============================================================
const useShops = (productSlug = 'sucre', neighborhoodSlug = '') => {
  const [shops, setShops] = React.useState([]);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    let cancelled = false;
    setLoading(true);
    const params = new URLSearchParams({ product_slug: productSlug });
    if (neighborhoodSlug) params.set('neighborhood_slug', neighborhoodSlug);
    api(`/api/pwa/shops?${params}`)
      .then((d) => { if (!cancelled) setShops(d.shops || []); })
      .catch(() => { if (!cancelled) setShops([]); })
      .finally(() => { if (!cancelled) setLoading(false); });
    return () => { cancelled = true; };
  }, [productSlug, neighborhoodSlug]);

  return { shops, loading };
};

// ============================================================
// HOOK : usePulseFeed (activité récente du quartier)
// ============================================================
const usePulseFeed = (neighborhoodSlug = '') => {
  const [feed, setFeed] = React.useState([]);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    const params = new URLSearchParams();
    if (neighborhoodSlug) params.set('neighborhood_slug', neighborhoodSlug);
    api(`/api/pwa/pulse?${params}`)
      .then((d) => setFeed(d.events || []))
      .catch(() => setFeed([]))
      .finally(() => setLoading(false));
  }, [neighborhoodSlug]);

  return { feed, loading };
};

// ============================================================
// HOOK : useAmbassador (espace personnel)
// ============================================================
const useAmbassador = (phone) => {
  const [data, setData] = React.useState(null);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    if (!phone) { setLoading(false); return; }
    api(`/api/pwa/ambassador/me?phone=${encodeURIComponent(phone)}`)
      .then((d) => setData(d))
      .catch(() => setData(null))
      .finally(() => setLoading(false));
  }, [phone]);

  return { data, loading };
};

// ============================================================
// HOOK : useTrustIndex (indice de confiance quartier)
// ============================================================
const useTrustIndex = (neighborhoodSlug = '') => {
  const [data, setData] = React.useState(null);
  React.useEffect(() => {
    const params = new URLSearchParams();
    if (neighborhoodSlug) params.set('neighborhood_slug', neighborhoodSlug);
    api(`/api/pwa/trust-index?${params}`)
      .then((d) => setData(d))
      .catch(() => setData(null));
  }, [neighborhoodSlug]);
  return data;
};

// ============================================================
// HOOK : useGroupBuys (groupes d'achat ouverts)
// ============================================================
const useGroupBuys = (neighborhoodSlug = '') => {
  const [groups, setGroups] = React.useState([]);
  React.useEffect(() => {
    const params = new URLSearchParams();
    if (neighborhoodSlug) params.set('neighborhood_slug', neighborhoodSlug);
    api(`/api/pwa/group-buys?${params}`)
      .then((d) => setGroups(d.groups || []))
      .catch(() => setGroups([]));
  }, [neighborhoodSlug]);
  return groups;
};

// ============================================================
// HOOK : useGeolocation
// V3.5 — Bug #2 : enableHighAccuracy=false (plus rapide sur PWA iOS),
// timeout JS de fallback à 12s pour ne jamais rester bloqué silencieusement,
// messages d'erreur traduits selon le code (PERMISSION_DENIED, etc.).
// ============================================================
const useGeolocation = () => {
  const [position, setPosition] = React.useState(null);
  const [error, setError] = React.useState(null);
  const [loading, setLoading] = React.useState(false);
  const fallbackTimerRef = React.useRef(null);

  const detect = React.useCallback(() => {
    if (!navigator.geolocation) {
      setError('Géolocalisation non disponible sur ce navigateur');
      return;
    }
    setError(null);
    setLoading(true);

    // Garde-fou : si le navigateur ne rappelle JAMAIS (cas iOS standalone parfois)
    if (fallbackTimerRef.current) clearTimeout(fallbackTimerRef.current);
    fallbackTimerRef.current = setTimeout(() => {
      setLoading(false);
      setError('Délai dépassé — vérifie que la localisation est autorisée pour Oveyo dans les Réglages.');
    }, 12000);

    navigator.geolocation.getCurrentPosition(
      (pos) => {
        if (fallbackTimerRef.current) { clearTimeout(fallbackTimerRef.current); fallbackTimerRef.current = null; }
        setPosition({ lat: pos.coords.latitude, lng: pos.coords.longitude });
        setLoading(false);
      },
      (err) => {
        if (fallbackTimerRef.current) { clearTimeout(fallbackTimerRef.current); fallbackTimerRef.current = null; }
        let msg = err.message || 'Erreur GPS';
        if (err.code === 1) msg = 'Permission refusée — autorise la localisation pour Oveyo dans Réglages → Safari → Localisation.';
        else if (err.code === 2) msg = 'Position indisponible — essaie en extérieur ou réessaie dans un instant.';
        else if (err.code === 3) msg = 'Délai dépassé — réessaie.';
        setError(msg);
        setLoading(false);
      },
      { enableHighAccuracy: false, timeout: 10000, maximumAge: 60000 }
    );
  }, []);

  return { position, error, loading, detect };
};

// ============================================================
// HOOK : useOnlineStatus
// ============================================================
const useOnlineStatus = () => {
  const [online, setOnline] = React.useState(navigator.onLine);
  React.useEffect(() => {
    const on = () => setOnline(true);
    const off = () => setOnline(false);
    window.addEventListener('online', on);
    window.addEventListener('offline', off);
    return () => {
      window.removeEventListener('online', on);
      window.removeEventListener('offline', off);
    };
  }, []);
  return online;
};

// ============================================================
// UTILS — formatage
// ============================================================
const formatRelative = (isoDate) => {
  if (!isoDate) return '';
  const d = new Date(isoDate);
  const diff = (Date.now() - d.getTime()) / 1000;
  if (diff < 60) return "à l'instant";
  if (diff < 3600) return `${Math.floor(diff / 60)} min`;
  if (diff < 86400) return `${Math.floor(diff / 3600)} h`;
  if (diff < 86400 * 7) return `${Math.floor(diff / 86400)} j`;
  return d.toLocaleDateString('fr-FR');
};

const formatPhone = (phone) => {
  if (!phone) return '';
  const clean = String(phone).replace(/\D/g, '');
  if (clean.startsWith('221') && clean.length === 12) {
    return `+221 ${clean.slice(3, 5)} ${clean.slice(5, 8)} ${clean.slice(8, 10)} ${clean.slice(10)}`;
  }
  return phone;
};

const compressImage = (file, maxDim = 1024, quality = 0.82) => {
  return new Promise((resolve, reject) => {
    const img = new Image();
    const url = URL.createObjectURL(file);
    img.onload = () => {
      let { width, height } = img;
      if (width > maxDim || height > maxDim) {
        const scale = maxDim / Math.max(width, height);
        width = Math.round(width * scale);
        height = Math.round(height * scale);
      }
      const canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;
      canvas.getContext('2d').drawImage(img, 0, 0, width, height);
      canvas.toBlob((blob) => resolve(blob), 'image/jpeg', quality);
      URL.revokeObjectURL(url);
    };
    img.onerror = reject;
    img.src = url;
  });
};

// Export globaux
window.OveyoState = {
  loadState,
  saveState,
  defaultState,
  api,
  usePrices,
  useCatalog,
  usePharmaciesOnDuty,
  useShops,
  usePulseFeed,
  useAmbassador,
  useTrustIndex,
  useGroupBuys,
  useGeolocation,
  useOnlineStatus,
  formatRelative,
  formatPhone,
  compressImage,
};
