// Error classifier — categorizes API errors for actionable user messaging

export type ApiErrorType =
  | 'rate_limit'
  | 'auth'
  | 'quota'
  | 'overloaded'
  | 'network'
  | 'ipc'
  | 'database'
  | 'filesystem'
  | 'unknown';

export interface ClassifiedError {
  type: ApiErrorType;
  message: string;
  retryable: boolean;
  /** Suggested retry delay in seconds (0 = no retry) */
  retryDelaySec: number;
}

const RATE_LIMIT_PATTERNS = [
  /rate.?limit/i,
  /429/,
  /too many requests/i,
  /rate_limit_error/i,
  /throttl/i,
];

const AUTH_PATTERNS = [
  /401/,
  /invalid.?api.?key/i,
  /authentication/i,
  /unauthorized/i,
  /invalid.?x-api-key/i,
  /api_key/i,
];

const QUOTA_PATTERNS = [
  /insufficient.?quota/i,
  /billing/i,
  /payment/i,
  /exceeded.*quota/i,
  /credit/i,
  /usage.?limit/i,
];

const OVERLOADED_PATTERNS = [
  /overloaded/i,
  /503/,
  /service.?unavailable/i,
  /capacity/i,
  /busy/i,
];

const NETWORK_PATTERNS = [
  /ECONNREFUSED/,
  /ECONNRESET/,
  /ETIMEDOUT/,
  /network/i,
  /fetch.?failed/i,
  /dns/i,
];

const IPC_PATTERNS = [
  /ipc.?error/i,
  /plugin.?not.?found/i,
  /command.?not.?found/i,
  /invoke.?failed/i,
  /tauri/i,
  /command.?rejected/i,
];

const DATABASE_PATTERNS = [
  /sqlite/i,
  /database.?locked/i,
  /database.?is.?locked/i,
  /rusqlite/i,
  /busy_timeout/i,
  /SQLITE_BUSY/i,
  /no.?such.?table/i,
  /constraint.?failed/i,
];

const FILESYSTEM_PATTERNS = [
  /ENOENT/,
  /EACCES/,
  /EPERM/,
  /no.?such.?file/i,
  /permission.?denied/i,
  /not.?found/i,
  /directory.?not.?empty/i,
];

function matchesAny(text: string, patterns: RegExp[]): boolean {
  return patterns.some(p => p.test(text));
}

/**
 * Classify an error message into an actionable category.
 */
export function classifyError(errorMessage: string): ClassifiedError {
  if (matchesAny(errorMessage, RATE_LIMIT_PATTERNS)) {
    return {
      type: 'rate_limit',
      message: 'Rate limited. The API will auto-retry shortly.',
      retryable: true,
      retryDelaySec: 30,
    };
  }

  if (matchesAny(errorMessage, AUTH_PATTERNS)) {
    return {
      type: 'auth',
      message: 'API key invalid or expired. Check Settings.',
      retryable: false,
      retryDelaySec: 0,
    };
  }

  if (matchesAny(errorMessage, QUOTA_PATTERNS)) {
    return {
      type: 'quota',
      message: 'API quota exceeded. Check your billing.',
      retryable: false,
      retryDelaySec: 0,
    };
  }

  if (matchesAny(errorMessage, OVERLOADED_PATTERNS)) {
    return {
      type: 'overloaded',
      message: 'API overloaded. Retrying shortly...',
      retryable: true,
      retryDelaySec: 15,
    };
  }

  if (matchesAny(errorMessage, NETWORK_PATTERNS)) {
    return {
      type: 'network',
      message: 'Network error. Check your connection.',
      retryable: true,
      retryDelaySec: 5,
    };
  }

  if (matchesAny(errorMessage, IPC_PATTERNS)) {
    return {
      type: 'ipc',
      message: 'Internal communication error. Try restarting.',
      retryable: true,
      retryDelaySec: 2,
    };
  }

  if (matchesAny(errorMessage, DATABASE_PATTERNS)) {
    return {
      type: 'database',
      message: 'Database error. Settings may not have saved.',
      retryable: true,
      retryDelaySec: 1,
    };
  }

  if (matchesAny(errorMessage, FILESYSTEM_PATTERNS)) {
    return {
      type: 'filesystem',
      message: 'File system error. Check permissions.',
      retryable: false,
      retryDelaySec: 0,
    };
  }

  return {
    type: 'unknown',
    message: errorMessage,
    retryable: false,
    retryDelaySec: 0,
  };
}
