/**
 * Standardized social publish error codes + retryability.
 */

export const SOCIAL_PUBLISH_ERROR_CODES = [
  "PLATFORM_DISABLED",
  "NOT_IMPLEMENTED",
  "MISSING_CREDENTIALS",
  "INVALID_CONFIGURATION",
  "ACCOUNT_NOT_CONNECTED",
  "TOKEN_EXPIRED",
  "TOKEN_REVOKED",
  "DESTINATION_NOT_SUPPORTED",
  "CONTENT_TYPE_NOT_SUPPORTED",
  "PROVIDER_ERROR",
  "RATE_LIMITED",
  "NETWORK_ERROR",
  "TIMEOUT",
  "TEMPORARY_PROVIDER_ERROR",
  "PUBLISH_FAILED",
  "COMING_SOON",
  "UNKNOWN_PLATFORM",
] as const;

export type SocialPublishErrorCode = (typeof SOCIAL_PUBLISH_ERROR_CODES)[number];

const RETRYABLE: ReadonlySet<SocialPublishErrorCode> = new Set([
  "NETWORK_ERROR",
  "RATE_LIMITED",
  "TEMPORARY_PROVIDER_ERROR",
  "TIMEOUT",
]);

export function isRetryableErrorCode(code: string | undefined): boolean {
  if (!code) return false;
  return RETRYABLE.has(code as SocialPublishErrorCode);
}

/** Classify provider/network failures into structured codes. */
export function classifyProviderError(message: string | undefined): {
  code: SocialPublishErrorCode;
  retryable: boolean;
} {
  const m = (message ?? "").toLowerCase();
  if (!m) {
    return { code: "PUBLISH_FAILED", retryable: false };
  }
  if (/rate.?limit|too many requests|throttl|429/.test(m)) {
    return { code: "RATE_LIMITED", retryable: true };
  }
  if (/timeout|timed out|etimedout|esockettimedout/.test(m)) {
    return { code: "TIMEOUT", retryable: true };
  }
  if (/network|econnreset|econnrefused|fetch failed|socket|enotfound|dns/.test(m)) {
    return { code: "NETWORK_ERROR", retryable: true };
  }
  if (/temporarily|try again|unavailable|503|502|504/.test(m)) {
    return { code: "TEMPORARY_PROVIDER_ERROR", retryable: true };
  }
  if (/revoked|invalid.?grant|permission.?denied/.test(m)) {
    return { code: "TOKEN_REVOKED", retryable: false };
  }
  if (/expired|invalid.?token|unauthorized|401/.test(m)) {
    return { code: "TOKEN_EXPIRED", retryable: false };
  }
  return { code: "PROVIDER_ERROR", retryable: false };
}

export function mapBlockCodeToPublishError(
  code: string,
): SocialPublishErrorCode {
  switch (code) {
    case "PLATFORM_DISABLED":
      return "PLATFORM_DISABLED";
    case "MISSING_CREDENTIALS":
      return "MISSING_CREDENTIALS";
    case "COMING_SOON":
      return "COMING_SOON";
    case "NOT_IMPLEMENTED":
      return "NOT_IMPLEMENTED";
    case "UNKNOWN_PLATFORM":
      return "UNKNOWN_PLATFORM";
    default:
      return "INVALID_CONFIGURATION";
  }
}
