'use strict';

const SERVER_EVENTS = new Set([
  'check_started',
  'check_completed',
  'check_failed',
  'update_available',
  'api_check',
  'apply_requested',
  'apply_ignored',
  'apply_started',
  'apply_spawn_error',
]);

const CLIENT_EVENTS = new Set([
  'ui_prompt_shown',
  'ui_action',
]);

const SURFACES = new Set(['banner', 'wizard', 'api', 'api_refresh', 'api_stale', 'startup', 'scheduled', 'manual', 'unknown']);
const ACTIONS = new Set(['later', 'skip', 'apply', 'apply_started', 'apply_failed', 'already_up_to_date']);
const RESULTS = new Set(['available', 'up_to_date', 'error', 'started', 'ignored']);

function cleanEnum(value, allowed, fallback = 'unknown') {
  const normalized = String(value || '').trim().toLowerCase().replace(/[^a-z0-9_-]/g, '_');
  return allowed.has(normalized) ? normalized : fallback;
}

function cleanVersion(value) {
  const raw = String(value || '').trim().replace(/^v/i, '');
  if (!raw || raw.length > 64) return '';
  return /^[0-9A-Za-z.+_-]+$/.test(raw) ? raw : '';
}

function cleanBool(value) {
  return value === true ? true : value === false ? false : undefined;
}

function errorKind(error) {
  const message = String(error?.message || error || '').toLowerCase();
  if (!message) return 'unknown';
  if (/timeout|timed out|abort/.test(message)) return 'timeout';
  if (/network|fetch|enotfound|eai_again|econn|socket/.test(message)) return 'network';
  if (/npm registry returned 4\d\d/.test(message)) return 'registry_client_error';
  if (/npm registry returned 5\d\d/.test(message)) return 'registry_server_error';
  if (/spawn|enoent/.test(message)) return 'spawn_error';
  return 'error';
}

function sanitizePayload(details = {}) {
  const payload = {};
  const source = cleanEnum(details.source, SURFACES, '');
  const surface = cleanEnum(details.surface, SURFACES, '');
  const action = cleanEnum(details.action, ACTIONS, '');
  const result = cleanEnum(details.result, RESULTS, '');
  const currentVersion = cleanVersion(details.currentVersion || details.current || details.current_version);
  const latestVersion = cleanVersion(details.latestVersion || details.latest || details.latest_version);
  const updateAvailable = cleanBool(details.updateAvailable);

  if (source) payload.source = source;
  if (surface) payload.surface = surface;
  if (action) payload.action = action;
  if (result) payload.result = result;
  if (currentVersion) payload.current_version = currentVersion;
  if (latestVersion) payload.latest_version = latestVersion;
  if (updateAvailable !== undefined) payload.update_available = updateAvailable;
  if (details.error || details.errorKind) payload.error_kind = details.errorKind || errorKind(details.error);

  return payload;
}

function trackUpdateTelemetry(telemetry, event, details = {}) {
  const normalized = cleanEnum(event, new Set([...SERVER_EVENTS, ...CLIENT_EVENTS]), '');
  if (!normalized) return false;
  try {
    telemetry?.track?.(`ctm_update_${normalized}`, sanitizePayload(details));
    return true;
  } catch {
    return false;
  }
}

function clientUpdateTelemetryEvent(body = {}) {
  const rawEvent = String(body.event || '').trim().toLowerCase();
  if (rawEvent === 'prompt_shown') {
    return {
      event: 'ui_prompt_shown',
      details: sanitizePayload({
        surface: body.surface,
        currentVersion: body.currentVersion,
        latestVersion: body.latestVersion,
      }),
    };
  }
  if (rawEvent === 'action') {
    return {
      event: 'ui_action',
      details: sanitizePayload({
        surface: body.surface,
        action: body.action,
        currentVersion: body.currentVersion,
        latestVersion: body.latestVersion,
      }),
    };
  }
  return null;
}

module.exports = {
  clientUpdateTelemetryEvent,
  errorKind,
  sanitizePayload,
  trackUpdateTelemetry,
};
