import {
  isDataMigrationComplete,
  listInboundMimeRepairCandidates,
  markDataMigrationComplete,
  updateInboundMessageMimeContent
} from './db.js';
import { decodeMimeHeader, parseInboundMessage } from './inbound-mail.js';

const migrationName = 'inbound-mime-content-v1';

export async function repairStoredInboundMime({ batchSize = 100 } = {}) {
  if (isDataMigrationComplete(migrationName)) return { repaired: 0, failed: 0 };

  let afterId = 0;
  let repaired = 0;
  let failed = 0;

  while (true) {
    const candidates = listInboundMimeRepairCandidates(afterId, batchSize);
    if (!candidates.length) break;

    for (const candidate of candidates) {
      afterId = candidate.id;
      try {
        const parsed = await parseInboundMessage(candidate.rawMessage, candidate.recipients);
        const decodedSubject = decodeMimeHeader(candidate.subject);
        const rawBody = extractRawBody(candidate.rawMessage);
        const storedBodyIsRaw = Boolean(rawBody) && candidate.textBody.trim() === rawBody.trim();
        const previewIsRaw = candidate.preview === normalizePreview(candidate.rawMessage);
        const nextMessage = {
          sender: candidate.sender,
          recipients: candidate.recipients,
          subject: decodedSubject,
          messageId: candidate.messageId,
          textBody: storedBodyIsRaw ? parsed.textBody : candidate.textBody,
          htmlBody: storedBodyIsRaw ? parsed.htmlBody : candidate.htmlBody
        };
        const changed = nextMessage.subject !== candidate.subject
          || nextMessage.textBody !== candidate.textBody
          || nextMessage.htmlBody !== candidate.htmlBody
          || previewIsRaw;
        const updated = changed && updateInboundMessageMimeContent(candidate.id, nextMessage);
        if (updated) repaired += 1;
      } catch {
        failed += 1;
      }
    }
  }

  if (!failed) markDataMigrationComplete(migrationName);
  return { repaired, failed };
}

function extractRawBody(rawMessage) {
  const source = String(rawMessage || '');
  const separator = source.match(/\r?\n\r?\n/);
  return separator ? source.slice(separator.index + separator[0].length) : '';
}

function normalizePreview(value) {
  return String(value || '').replace(/\s+/g, ' ').trim().slice(0, 240);
}
