import { trace } from "./debug-trace.js";
import { logger } from "../monitoring/logger.js";
function TraceLinearAPI(target, propertyKey, descriptor) {
  const originalMethod = descriptor.value;
  const isAsync = originalMethod.constructor.name === "AsyncFunction";
  if (isAsync) {
    descriptor.value = async function(...args) {
      const className = target.constructor.name;
      const methodName = `${className}.${propertyKey}`;
      const context = extractAPIContext(propertyKey, args);
      return trace.traceAsync("api", methodName, context, async () => {
        const startTime = Date.now();
        try {
          logger.debug(`Linear API Call: ${methodName}`, context);
          const result = await originalMethod.apply(this, args);
          const duration = Date.now() - startTime;
          logger.info(`Linear API Success: ${methodName}`, {
            duration,
            resultType: Array.isArray(result) ? `array[${result.length}]` : typeof result,
            hasData: result != null
          });
          if (duration > 1e3) {
            logger.warn(
              `Slow Linear API call: ${methodName} took ${duration}ms`,
              {
                ...context,
                duration
              }
            );
          }
          return result;
        } catch (error) {
          const duration = Date.now() - startTime;
          logger.error(`Linear API Failed: ${methodName}`, error, {
            ...context,
            duration,
            errorCode: error.code,
            statusCode: error.statusCode,
            graphQLErrors: error.errors
          });
          if (error.message?.includes("rate limit")) {
            logger.warn("Rate limit hit - consider implementing backoff", {
              method: methodName,
              suggestion: "Implement exponential backoff or request queuing"
            });
          } else if (error.message?.includes("network")) {
            logger.warn("Network error - check connectivity", {
              method: methodName,
              suggestion: "Verify API endpoint and network connectivity"
            });
          } else if (error.message?.includes("unauthorized")) {
            logger.warn("Authorization error - check API key", {
              method: methodName,
              suggestion: "Verify LINEAR_API_KEY is set and valid"
            });
          }
          throw error;
        }
      });
    };
  } else {
    descriptor.value = function(...args) {
      const className = target.constructor.name;
      const methodName = `${className}.${propertyKey}`;
      const context = extractAPIContext(propertyKey, args);
      return trace.traceSync("api", methodName, context, () => {
        return originalMethod.apply(this, args);
      });
    };
  }
  return descriptor;
}
function extractAPIContext(methodName, args) {
  const context = {};
  if (methodName === "createIssue" && args[0]) {
    context.title = args[0].title;
    context.teamId = args[0].teamId;
    context.priority = args[0].priority;
  } else if (methodName === "updateIssue" && args[0]) {
    context.issueId = args[0];
    context.updates = Object.keys(args[1] || {});
  } else if (methodName === "getIssue") {
    context.issueId = args[0];
  } else if (methodName === "getIssues" && args[0]) {
    context.filter = args[0];
  } else if (methodName === "graphql") {
    const query = args[0];
    if (query) {
      const match = query.match(/(?:query|mutation)\s+(\w+)/);
      context.operation = match ? match[1] : "unknown";
      context.queryLength = query.length;
      context.variables = args[1] ? Object.keys(args[1]) : [];
    }
  }
  return context;
}
function createTracedFetch(baseFetch = fetch) {
  return async function tracedFetch(input, init) {
    const url = typeof input === "string" ? input : input.toString();
    const method = init?.method || "GET";
    const headers = init?.headers ? { ...init.headers } : {};
    if (headers.Authorization) {
      headers.Authorization = headers.Authorization.substring(0, 20) + "...[MASKED]";
    }
    const context = {
      method,
      url: url.length > 100 ? url.substring(0, 100) + "..." : url,
      headers: Object.keys(headers),
      bodySize: init?.body ? JSON.stringify(init.body).length : 0
    };
    return trace.api(method, url, context, async () => {
      const startTime = Date.now();
      try {
        const response = await baseFetch(input, init);
        const duration = Date.now() - startTime;
        logger.debug(`HTTP ${method} ${response.status}`, {
          url: url.substring(0, 100),
          status: response.status,
          duration,
          headers: {
            "content-type": response.headers.get("content-type"),
            "x-ratelimit-remaining": response.headers.get(
              "x-ratelimit-remaining"
            ),
            "x-ratelimit-reset": response.headers.get("x-ratelimit-reset")
          }
        });
        const remaining = response.headers.get("x-ratelimit-remaining");
        if (remaining && parseInt(remaining) < 10) {
          logger.warn(`Low rate limit remaining: ${remaining}`, {
            url: url.substring(0, 100),
            resetAt: response.headers.get("x-ratelimit-reset")
          });
        }
        if (duration > 2e3) {
          logger.warn(`Slow HTTP response: ${duration}ms`, {
            method,
            url: url.substring(0, 100),
            status: response.status
          });
        }
        return response;
      } catch (error) {
        const duration = Date.now() - startTime;
        logger.error(`HTTP ${method} failed`, error, {
          url: url.substring(0, 100),
          duration,
          errorType: error.constructor.name,
          errno: error.errno,
          code: error.code
        });
        throw error;
      }
    });
  };
}
function wrapGraphQLClient(client) {
  const prototype = Object.getPrototypeOf(client);
  const propertyNames = Object.getOwnPropertyNames(prototype);
  for (const propertyName of propertyNames) {
    if (propertyName === "constructor") continue;
    const descriptor = Object.getOwnPropertyDescriptor(prototype, propertyName);
    if (!descriptor || typeof descriptor.value !== "function") continue;
    TraceLinearAPI(prototype, propertyName, descriptor);
    Object.defineProperty(prototype, propertyName, descriptor);
  }
  return client;
}
export {
  TraceLinearAPI,
  createTracedFetch,
  wrapGraphQLClient
};
//# sourceMappingURL=linear-api-wrapper.js.map
