/**
 * src/integrations/collabSupport/client.js
 *
 * Shared HTTP client for CollabSupport (collabFinder) read endpoints.
 * Used by /woSummary, /woHistory, /avStatus, and /woAttachments.
 */

import { logger } from '../../utils/logger.js';

const DEFAULT_TIMEOUT_MS = 60_000;

/** Usage-markdown prefixes returned by collabFinder before HTTP 400 alignment. */
const USAGE_MARKERS = [
  '**Work Order Summary Usage:**',
  '**Work Order History Usage:**',
  'Please provide a 2–4 digit store number.',
];

export function getCollabSupportBase() {
  // CS_API_BASE_INTERNAL is for Docker: reach collabFinder on the compose
  // network (http://collabfinder:1800) instead of the public URL, which often
  // fails from inside a container (hairpin NAT / DNS to the host's public IP).
  const raw = process.env.CS_API_BASE_INTERNAL || process.env.CS_API_BASE;
  if (!raw) return null;
  return raw.replace(/\/+$/, '');
}

function buildUrl(path, params = {}) {
  const base = getCollabSupportBase();
  if (!base) {
    throw new Error('CS_API_BASE is not configured');
  }
  const normalizedPath = path.startsWith('/') ? path : `/${path}`;
  const url = new URL(`${base}${normalizedPath}`);
  for (const [key, value] of Object.entries(params)) {
    if (value !== undefined && value !== null && value !== '') {
      url.searchParams.set(key, String(value));
    }
  }
  return url;
}

function formatFetchError(err) {
  if (err.name === 'AbortError') return 'Request timed out';
  const cause = err.cause;
  const causeMsg = cause && (cause.message || cause.code);
  if (causeMsg && causeMsg !== err.message) {
    return `${err.message} (${causeMsg})`;
  }
  return err.message || String(err);
}

async function fetchWithTimeout(url, options = {}, timeoutMs = DEFAULT_TIMEOUT_MS) {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);
  try {
    return await fetch(url, { ...options, signal: controller.signal });
  } finally {
    clearTimeout(timer);
  }
}

function looksLikeUsageMarkdown(text) {
  if (!text || typeof text !== 'string') return false;
  return USAGE_MARKERS.some((marker) => text.includes(marker));
}

/**
 * GET a markdown endpoint from CollabSupport.
 * @returns {{ ok: boolean, status: number, markdown: string, elapsedMs: number, isUsageResponse?: boolean }}
 */
export async function fetchCollabMarkdown(path, params = {}, { logTag = 'collabSupport', timeoutMs } = {}) {
  const url = buildUrl(path, params);
  const started = Date.now();
  logger(logTag, `GET ${url}`);

  let response;
  try {
    response = await fetchWithTimeout(url, {}, timeoutMs ?? DEFAULT_TIMEOUT_MS);
  } catch (err) {
    const elapsedMs = Date.now() - started;
    const msg = formatFetchError(err);
    logger(logTag, `GET ${url} → error (${elapsedMs}ms): ${msg}`, 'error');
    throw new Error(msg);
  }

  const elapsedMs = Date.now() - started;
  const markdown = await response.text();
  logger(logTag, `GET ${url} → ${response.status} (${elapsedMs}ms)`);

  const isUsageResponse = response.ok && looksLikeUsageMarkdown(markdown);

  return {
    ok: response.ok,
    status: response.status,
    markdown,
    elapsedMs,
    isUsageResponse,
  };
}

/**
 * GET a JSON endpoint from CollabSupport.
 * @returns {{ ok: boolean, status: number, data: object, elapsedMs: number }}
 */
export async function fetchCollabJson(path, params = {}, { logTag = 'collabSupport', timeoutMs } = {}) {
  const url = buildUrl(path, params);
  const started = Date.now();
  logger(logTag, `GET ${url}`);

  let response;
  try {
    response = await fetchWithTimeout(url, {
      headers: { Accept: 'application/json' },
    }, timeoutMs ?? DEFAULT_TIMEOUT_MS);
  } catch (err) {
    const elapsedMs = Date.now() - started;
    const msg = formatFetchError(err);
    logger(logTag, `GET ${url} → error (${elapsedMs}ms): ${msg}`, 'error');
    throw new Error(msg);
  }

  const elapsedMs = Date.now() - started;
  let data;
  try {
    data = await response.json();
  } catch {
    data = {};
  }
  logger(logTag, `GET ${url} → ${response.status} (${elapsedMs}ms)`);

  return { ok: response.ok, status: response.status, data, elapsedMs };
}

export function assertCollabSupportConfigured() {
  if (!getCollabSupportBase()) {
    throw new Error('CS_API_BASE is not configured');
  }
}

export default {
  getCollabSupportBase,
  fetchCollabMarkdown,
  fetchCollabJson,
  assertCollabSupportConfigured,
};
