import { ApiError, submitPrompt } from '../api/client';
import type { AgentConfig } from '../config/store';
import { dueRows, markDelivered, markFailed, markRetry, pendingCount } from '../storage/queue';

export interface FlushResult {
  delivered: number;
  stillPending: number;
  authInvalid: boolean;
}

/**
 * Drain due rows from the offline queue. Stops early if the device token
 * turns out to be invalid/revoked so we don't burn through the whole queue
 * retrying a credential that will never succeed.
 */
export async function flushQueue(config: AgentConfig): Promise<FlushResult> {
  let delivered = 0;
  let authInvalid = false;

  for (const row of dueRows()) {
    if (authInvalid) {
      break;
    }

    try {
      await submitPrompt(config.apiBaseUrl, config.deviceToken, {
        promptId: row.payload.promptId,
        sessionId: row.payload.sessionId,
        prompt: row.payload.prompt,
        submittedAt: row.payload.submittedAt,
        projectName: row.payload.projectName,
        projectPathHash: row.payload.projectPathHash,
        projectDetectionSource: row.payload.projectDetectionSource,
        clientVersion: row.payload.clientVersion,
      });

      markDelivered(row.id);
      delivered += 1;
    } catch (error) {
      if (error instanceof ApiError && (error.status === 401 || error.status === 403)) {
        authInvalid = true;
        continue;
      }

      if (error instanceof ApiError && error.status !== null && error.status >= 400 && error.status < 500) {
        // Not transient (bad payload) - stop retrying but keep the record for inspection.
        markFailed(row.id);
        continue;
      }

      markRetry(row.id, row.attempts + 1);
    }
  }

  return { delivered, stillPending: pendingCount(), authInvalid };
}
