// ROAMR integration bridge.
// Public config can be read in the browser. Private providers stay behind
// Next.js API routes so OpenRouteService/OpenAI keys are never exposed.

window.ROAMR_CONFIG = {
  ok: false,
  maps: { provider: 'placeholder', mapTilerKey: null },
  supabase: { url: null, anonKey: null },
  services: { openRouteService: false, openAI: false, supabase: false },
};

window.ROAMR_STATE = { user: null, profile: null };

window.ROAMR_CONFIG_READY = fetch('/api/integrations/config')
  .then((res) => res.ok ? res.json() : Promise.reject(new Error('Config failed')))
  .then((config) => {
    window.ROAMR_CONFIG = config;
    window.dispatchEvent(new CustomEvent('roamr:config', { detail: config }));
    return config;
  })
  .catch((error) => {
    console.warn('ROAMR config unavailable', error);
    return window.ROAMR_CONFIG;
	  });

window.ROAMR_AUTH_READY = window.ROAMR_CONFIG_READY.then(async (config) => {
  if (!config?.supabase?.url || !config?.supabase?.anonKey || !window.supabase?.createClient) {
    return window.ROAMR_STATE;
  }
  window.ROAMR_SUPABASE = window.supabase.createClient(config.supabase.url, config.supabase.anonKey);
  const { data } = await window.ROAMR_SUPABASE.auth.getSession();
  window.ROAMR_STATE.user = data.session?.user || null;
  window.dispatchEvent(new CustomEvent('roamr:auth', { detail: window.ROAMR_STATE }));
  window.ROAMR_SUPABASE.auth.onAuthStateChange((_event, session) => {
    window.ROAMR_STATE.user = session?.user || null;
    window.dispatchEvent(new CustomEvent('roamr:auth', { detail: window.ROAMR_STATE }));
  });
  return window.ROAMR_STATE;
});

async function roamrAuthHeader() {
  await window.ROAMR_AUTH_READY;
  const session = await window.ROAMR_SUPABASE?.auth.getSession();
  const token = session?.data?.session?.access_token;
  return token ? { authorization: `Bearer ${token}` } : {};
}

window.ROAMR_API = {
  async geocode(query) {
    const res = await fetch(`/api/maps/geocode?q=${encodeURIComponent(query)}`);
    const data = await res.json();
    if (!res.ok || !data.ok) throw new Error(data.error || 'Geocoding failed');
    return data;
  },

  async routeBuilder(prompt) {
    const res = await fetch('/api/ai/route-builder', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ prompt }),
    });
    const data = await res.json();
    if (!res.ok || !data.ok) throw new Error(data.error || 'Route builder failed');
    return data;
  },

  async gpxHealth(filename) {
    const res = await fetch('/api/gpx/health', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ filename }),
    });
    const data = await res.json();
    if (!res.ok || !data.ok) throw new Error(data.error || 'GPX health check failed');
    return data;
  },

  async route(start, end, profile = 'cycling-regular') {
    const res = await fetch('/api/maps/route', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ start, end, profile }),
    });
    const data = await res.json();
    if (!res.ok || !data.ok) throw new Error(data.error || 'Routing failed');
    return data;
  },

  async signUp(email, password) {
    await window.ROAMR_AUTH_READY;
    const { data, error } = await window.ROAMR_SUPABASE.auth.signUp({ email, password });
    if (error) throw new Error(error.message);
    window.ROAMR_STATE.user = data.user || data.session?.user || null;
    return data;
  },

  async signIn(email, password) {
    await window.ROAMR_AUTH_READY;
    const { data, error } = await window.ROAMR_SUPABASE.auth.signInWithPassword({ email, password });
    if (error) throw new Error(error.message);
    window.ROAMR_STATE.user = data.user || null;
    return data;
  },

  async signOut() {
    await window.ROAMR_AUTH_READY;
    const { error } = await window.ROAMR_SUPABASE.auth.signOut();
    if (error) throw new Error(error.message);
    window.ROAMR_STATE.user = null;
  },

  async profile() {
    const headers = await roamrAuthHeader();
    const res = await fetch('/api/profile/me', { headers });
    const data = await res.json();
    if (!res.ok || !data.ok) throw new Error(data.error || 'Profile unavailable');
    window.ROAMR_STATE.profile = data.profile;
    return data.profile;
  },

  async saveRoute(route) {
    const headers = { 'content-type': 'application/json', ...(await roamrAuthHeader()) };
    const res = await fetch('/api/routes/saved', {
      method: 'POST',
      headers,
      body: JSON.stringify({ route }),
    });
    const data = await res.json();
    if (!res.ok || !data.ok) throw new Error(data.error || 'Save failed');
    window.dispatchEvent(new CustomEvent('roamr:saves-changed'));
    return data.route;
  },

  async unsaveRoute(slug) {
    const headers = await roamrAuthHeader();
    const res = await fetch(`/api/routes/saved?slug=${encodeURIComponent(slug)}`, { method: 'DELETE', headers });
    const data = await res.json();
    if (!res.ok || !data.ok) throw new Error(data.error || 'Unsave failed');
    window.dispatchEvent(new CustomEvent('roamr:saves-changed'));
    return data;
  },

  async savedRoutes() {
    const headers = await roamrAuthHeader();
    const res = await fetch('/api/routes/saved', { headers });
    const data = await res.json();
    if (!res.ok || !data.ok) throw new Error(data.error || 'Saved routes unavailable');
    return data.routes || [];
  },

  async submitReport(route, note, category = 'ground_report', severity = 'medium') {
    const headers = { 'content-type': 'application/json', ...(await roamrAuthHeader()) };
    const res = await fetch('/api/reports', {
      method: 'POST',
      headers,
      body: JSON.stringify({ route, note, category, severity }),
    });
    const data = await res.json();
    if (!res.ok || !data.ok) throw new Error(data.error || 'Report failed');
    return data.report;
  },

  async adminReports() {
    const headers = await roamrAuthHeader();
    const res = await fetch('/api/admin/reports', { headers });
    const data = await res.json();
    if (!res.ok || !data.ok) throw new Error(data.error || 'Admin reports unavailable');
    return data.reports || [];
  },

  async updateReport(id, status) {
    const headers = { 'content-type': 'application/json', ...(await roamrAuthHeader()) };
    const res = await fetch('/api/admin/reports', {
      method: 'PATCH',
      headers,
      body: JSON.stringify({ id, status }),
    });
    const data = await res.json();
    if (!res.ok || !data.ok) throw new Error(data.error || 'Report update failed');
    return data.report;
  },
};

function roamrLonLatToTile(lon, lat, z) {
  const latRad = lat * Math.PI / 180;
  const n = 2 ** z;
  return {
    x: Math.floor((lon + 180) / 360 * n),
    y: Math.floor((1 - Math.asinh(Math.tan(latRad)) / Math.PI) / 2 * n),
  };
}

window.ROAMR_MAP = {
  outdoorTileUrl(x, y, z) {
    const key = window.ROAMR_CONFIG?.maps?.mapTilerKey;
    if (!key) return null;
    return `https://api.maptiler.com/maps/outdoor-v2/${z}/${x}/${y}.png?key=${encodeURIComponent(key)}`;
  },

  peakDistrictTiles() {
    const key = window.ROAMR_CONFIG?.maps?.mapTilerKey;
    if (!key) return [];
    const z = 10;
    const center = roamrLonLatToTile(-1.82, 53.35, z);
    const tiles = [];
    for (let dy = -1; dy <= 1; dy += 1) {
      for (let dx = -1; dx <= 1; dx += 1) {
        const x = center.x + dx;
        const y = center.y + dy;
        tiles.push({ x, y, z, dx, dy, url: window.ROAMR_MAP.outdoorTileUrl(x, y, z) });
      }
    }
    return tiles;
  },
};
