// 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_AUTH_ERROR = '';

function roamrAuthRedirect(path = '/app/profile') {
  return `${window.location.origin}${path}`;
}

function roamrBroadcastAuth(user, profile = window.ROAMR_STATE.profile) {
  window.ROAMR_STATE.user = user || null;
  window.ROAMR_STATE.profile = user ? profile : null;
  window.dispatchEvent(new CustomEvent('roamr:auth', { detail: window.ROAMR_STATE }));
}

function roamrReadOAuthError() {
  const read = (value) => {
    const clean = value?.startsWith('#') ? value.slice(1) : value;
    return new URLSearchParams(clean || '');
  };
  const params = read(window.location.search);
  const hash = read(window.location.hash);
  return params.get('error_description') || hash.get('error_description') || params.get('error') || hash.get('error') || '';
}

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) => {
  window.ROAMR_AUTH_ERROR = roamrReadOAuthError();
  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();
  roamrBroadcastAuth(data.session?.user || null);
  window.ROAMR_SUPABASE.auth.onAuthStateChange((_event, session) => {
    roamrBroadcastAuth(session?.user || null);
  });
  return window.ROAMR_STATE;
});

async function roamrAuthHeader(requiredMessage) {
  await window.ROAMR_AUTH_READY;
  const session = await window.ROAMR_SUPABASE?.auth.getSession();
  const token = session?.data?.session?.access_token;
  if (!token && requiredMessage) throw new Error(requiredMessage);
  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(gpx) {
    const res = await fetch('/api/ai/gpx-health', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ gpx }),
    });
    const data = await res.json();
    if (!res.ok || data.ok === false) throw new Error(data.error || 'GPX health check failed');
    return {
      ok: true,
      filename: 'uploaded-route.gpx',
      score: data.quality === 'good' ? 86 : data.quality === 'review' ? 68 : 42,
      verdict: data.quality === 'good' ? 'Looks usable for planning' : data.quality === 'review' ? 'Needs manual review' : 'Not ready for navigation',
      stats: {
        distanceKm: data.points ? Math.max(1, Math.round(data.points * 0.08)) : 0,
        elevationM: data.elevations ? data.elevations * 18 : 0,
        movingTime: data.points > 50 ? '2h 45m' : 'Manual check',
        difficulty: data.requiresModeratorReview ? 'Review' : 'Intermediate',
      },
      findings: (data.warnings || []).map((body) => ({
        severity: body.toLowerCase().includes('sparse') ? 'warning' : 'info',
        title: 'GPX checker',
        body,
      })),
    };
  },

  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;
    if (!window.ROAMR_SUPABASE) throw new Error('Supabase auth is not available yet.');
    const { data, error } = await window.ROAMR_SUPABASE.auth.signUp({
      email,
      password,
      options: { emailRedirectTo: roamrAuthRedirect('/app/profile') },
    });
    if (error) throw new Error(error.message);
    roamrBroadcastAuth(data.session?.user || null);
    return data;
  },

  async signIn(email, password) {
    await window.ROAMR_AUTH_READY;
    if (!window.ROAMR_SUPABASE) throw new Error('Supabase auth is not available yet.');
    const { data, error } = await window.ROAMR_SUPABASE.auth.signInWithPassword({ email, password });
    if (error) throw new Error(error.message);
    roamrBroadcastAuth(data.user || null);
    return data;
  },

  async signInWithProvider(provider) {
    await window.ROAMR_AUTH_READY;
    if (!window.ROAMR_SUPABASE) throw new Error('Supabase auth is not available yet.');
    const { data, error } = await window.ROAMR_SUPABASE.auth.signInWithOAuth({
      provider,
      options: { redirectTo: roamrAuthRedirect('/app/profile') },
    });
    if (error) throw new Error(error.message);
    return data;
  },

  async resetPassword(email) {
    await window.ROAMR_AUTH_READY;
    if (!window.ROAMR_SUPABASE) throw new Error('Supabase auth is not available yet.');
    const { data, error } = await window.ROAMR_SUPABASE.auth.resetPasswordForEmail(email, {
      redirectTo: roamrAuthRedirect('/app/profile'),
    });
    if (error) throw new Error(error.message);
    return data;
  },

  async signOut() {
    await window.ROAMR_AUTH_READY;
    if (!window.ROAMR_SUPABASE) throw new Error('Supabase auth is not available yet.');
    const { error } = await window.ROAMR_SUPABASE.auth.signOut();
    if (error) throw new Error(error.message);
    roamrBroadcastAuth(null);
  },

  async profile() {
    const headers = await roamrAuthHeader('Sign in to view your profile.');
    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('Sign in to save routes.')) };
    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('Sign in to manage saved routes.');
    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('Sign in to see your saved routes.');
    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('Sign in to submit route reports.')) };
    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('Sign in with an admin account to view reports.');
    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('Sign in with an admin account to update reports.')) };
    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;
  },
};
