// Thin wrapper around Cortaly's public surf API — the exact same endpoints
// public/assets/js/surf.js calls, just from the extension's background
// script instead of a loaded page. No CORS setup is needed server-side:
// with host_permissions covering the target origin (see manifest.json),
// the browser exempts extension-initiated fetch()es from same-origin
// policy. `credentials: 'include'` keeps the PHP session cookie (and thus
// the CSRF token bound to it) alive across every call in a run.
const CORTALY_BASE = 'https://cortaly.com';

const CortalyApi = {
  csrfToken: null,

  async ensureCsrfToken() {
    if (this.csrfToken) return this.csrfToken;
    const res = await fetch(`${CORTALY_BASE}/api/csrf-token.php`, { credentials: 'include' });
    const data = await res.json();
    this.csrfToken = data.csrf_token;
    return this.csrfToken;
  },

  async post(path, body) {
    const doRequest = async (token) => {
      const res = await fetch(`${CORTALY_BASE}/api/${path}`, {
        method: 'POST',
        credentials: 'include',
        // X-Cortaly-Client tells surf-next.php it's safe to serve a
        // frame_blocked/mixed_content_blocked site — the extension always
        // direct-navigates a real tab (background.js's ensureSurfTab()),
        // never an iframe, so those flags don't apply to it. Not meant as
        // a security boundary (a page could set the same header on its own
        // fetch), just an identification signal — nothing financial hinges
        // on it, worst case a spoofed value gets served a site that fails
        // to load in an iframe, same as before this existed.
        headers: { 'Content-Type': 'application/json', 'X-Cortaly-Client': 'extension' },
        body: JSON.stringify({ ...body, csrf_token: token }),
      });
      return res.json();
    };

    const token = await this.ensureCsrfToken();
    const data = await doRequest(token);
    // A csrf failure most likely means the session behind our cached token
    // expired (long-idle extension, browser restart, etc.) — fetch a fresh
    // one and retry exactly once, same as a normal page reload would get a
    // fresh token automatically.
    if (!data.ok && data.error === 'csrf') {
      this.csrfToken = null;
      const freshToken = await this.ensureCsrfToken();
      return doRequest(freshToken);
    }
    return data;
  },

  async get(path, params) {
    const qs = new URLSearchParams(params).toString();
    const res = await fetch(`${CORTALY_BASE}/api/${path}?${qs}`, { credentials: 'include' });
    return res.json();
  },

  next(username) {
    return this.post('surf-next.php', { username });
  },
  heartbeat(hitId, token) {
    return this.post('surf-heartbeat.php', { hit_id: hitId, token });
  },
  confirm(hitId, token) {
    return this.post('surf-confirm.php', { hit_id: hitId, token });
  },
  skip(hitId, token) {
    return this.post('surf-skip.php', { hit_id: hitId, token });
  },
  envCheck(hitId, token, adblockDetected, speedKbps) {
    return this.post('surf-envcheck.php', {
      hit_id: hitId, token, adblock_detected: adblockDetected, speed_kbps: speedKbps,
    });
  },
  collectJackpot(hitId, token) {
    return this.post('surf-jackpot-collect.php', { hit_id: hitId, token });
  },
  banner(username) {
    return this.get('surf-banner.php', { username });
  },

  // PTC (bidding-mode campaigns, 2026-07-23) — same shape as the
  // surf endpoints above, a parallel one-shot flow instead of a continuous
  // rotation. clickStart's X-Cortaly-Client header (set by post() already)
  // is what ClickService::startClick() requires for a bid-mode campaign.
  clickStart(campaignId) {
    return this.post('click-start.php', { campaign_id: campaignId });
  },
  clickHeartbeat(hitId, token) {
    return this.post('click-heartbeat.php', { hit_id: hitId, token });
  },
  clickEnvCheck(hitId, token, adblockDetected, speedKbps) {
    return this.post('click-envcheck.php', {
      hit_id: hitId, token, adblock_detected: adblockDetected, speed_kbps: speedKbps,
    });
  },
  clickConfirm(hitId, token) {
    return this.post('click-confirm.php', { hit_id: hitId, token });
  },
  clickSkip(hitId, token) {
    return this.post('click-skip.php', { hit_id: hitId, token });
  },
};
