const REQUEST_DEDUPE_WINDOW_MS = 60 * 1000;
const REQUEST_CORRELATION_WINDOW_MS = 5 * 60 * 1000;
const OBSERVED_REQUEST_RECORDING_SOURCE = "vendorget_background_mirror";
const observedRequestFingerprints = new Map();

async function handleObservedRequest(details) {
  if (!(await isRequestMonitoringEnabled())) {
    return;
  }

  if (!hasConsentQueryParam(details.url)) {
    return;
  }

  if (isEvidenceWriteSuspended()) {
    console.info("VendorGet-IV evidence write skipped: maintenance mode");
    return;
  }

  // The browser request is the primary observation; VG-IV records a mirror copy
  // with its own recordedAt timestamp for provenance.
  const requestFingerprint = await buildObservedRequestFingerprint(details);
  const requestFingerprintSource = buildObservedRequestFingerprintSource(details);
  const observedAt = new Date(details.timeStamp).toISOString();
  const recordedAt = new Date().toISOString();
  const correlation = buildObservedRequestCorrelation(
    details.tabId,
    details.frameId,
    observedAt
  );
  const now = Date.now();
  const existingFingerprint = observedRequestFingerprints.get(requestFingerprint);
  const observedRequest = {
    schemaVersion: 1,
    requestFingerprint: requestFingerprint,
    requestFingerprintSource: requestFingerprintSource,
    recordedAt: recordedAt,
    recordingSource: OBSERVED_REQUEST_RECORDING_SOURCE,
    firstSeenAt: observedAt,
    lastSeenAt: observedAt,
    seenCount: 1,
    request: {
      url: details.url,
      origin: requestFingerprintSource.origin,
      pathname: requestFingerprintSource.pathname,
      method: details.method,
      type: details.type,
      thirdParty: details.thirdParty
    },
    consentParams: {
      gdpr: requestFingerprintSource.consentParams.gdpr,
      gdpr_consent: requestFingerprintSource.consentParams.gdpr_consent,
      addtlConsent: requestFingerprintSource.consentParams.addtlConsent
    },
    context: {
      tabId: details.tabId,
      frameId: details.frameId
    },
    correlation: correlation
  };

  if (
    existingFingerprint &&
    now - existingFingerprint.lastSeenAt < REQUEST_DEDUPE_WINDOW_MS
  ) {
    existingFingerprint.lastSeenAt = now;
    existingFingerprint.seenCount += 1;
    await persistObservedRequest(observedRequest);
    return;
  }

  const seenCount = existingFingerprint
    ? existingFingerprint.seenCount + 1
    : 1;

  observedRequestFingerprints.set(requestFingerprint, {
    lastSeenAt: now,
    seenCount: seenCount
  });

  await persistObservedRequest(observedRequest);

  const normalizedObject = {
    observedAt: observedAt,
    recordedAt: recordedAt,
    requestId: details.requestId,
    tabId: details.tabId,
    frameId: details.frameId,
    url: details.url,
    method: details.method,
    type: details.type,
    thirdParty: details.thirdParty,
    requestFingerprint: requestFingerprint,
    seenCount: seenCount,
    requestFingerprintSource: requestFingerprintSource
  };

  console.log("VendorGet-IV observed request", normalizedObject);
}

function hasConsentQueryParam(url) {
  try {
    const params = new URL(url).searchParams;

    return (
      params.has("gdpr") ||
      params.has("gdpr_consent") ||
      params.has("addtlConsent")
    );
  } catch (error) {
    return false;
  }
}

function buildObservedRequestCorrelation(tabId, frameId, observedAt) {
  const latestConsentState = getLatestConsentStateForRequest(tabId, frameId);

  if (!latestConsentState) {
    return buildEmptyObservedRequestCorrelation();
  }

  const requestTime = Date.parse(observedAt);
  const consentTime = Date.parse(latestConsentState.capturedAt);

  if (!Number.isFinite(requestTime) || !Number.isFinite(consentTime)) {
    return buildEmptyObservedRequestCorrelation();
  }

  const deltaMs = requestTime - consentTime;

  if (deltaMs < 0 || deltaMs > REQUEST_CORRELATION_WINDOW_MS) {
    return buildEmptyObservedRequestCorrelation();
  }

  return {
    stateFingerprint: latestConsentState.stateFingerprint,
    deltaMs: deltaMs,
    method: "latest_in_memory_same_tab_frame",
    windowMs: REQUEST_CORRELATION_WINDOW_MS
  };
}

function buildEmptyObservedRequestCorrelation() {
  return {
    stateFingerprint: null,
    deltaMs: null,
    method: null,
    windowMs: REQUEST_CORRELATION_WINDOW_MS
  };
}
