'use strict';

function _contentText(content) {
  if (typeof content === 'string') return content;
  if (!Array.isArray(content)) return '';
  return content
    .filter((part) => part && part.type === 'text' && typeof part.text === 'string')
    .map((part) => part.text)
    .join('\n');
}

function _contentHasPayload(content) {
  if (typeof content === 'string') return content.length > 0;
  if (!Array.isArray(content)) return false;
  return content.some((part) => {
    if (!part || typeof part !== 'object') return false;
    if (part.type === 'text') return typeof part.text === 'string' && part.text.length > 0;
    return Boolean(part.type);
  });
}

function _normalizeMessage(item) {
  if (!item || typeof item !== 'object') return null;
  const role = String(item.role || '').trim();
  if (role !== 'user' && role !== 'assistant') return null;
  const content = Object.prototype.hasOwnProperty.call(item, 'content') ? item.content : item.text;
  if (!_contentHasPayload(content)) return null;
  return { role, content };
}

function _sameUserTurn(message, currentMessage) {
  if (!message || message.role !== 'user') return false;
  return _contentText(message.content) === currentMessage;
}

function _lastUserIndex(messages, currentMessage) {
  let fallback = -1;
  for (let i = messages.length - 1; i >= 0; i--) {
    if (messages[i]?.role !== 'user') continue;
    if (fallback === -1) fallback = i;
    if (_sameUserTurn(messages[i], currentMessage)) return i;
  }
  return fallback;
}

function createEmptyProviderMessagesError(context = {}) {
  const provider = context.provider || 'unknown';
  const model = context.model || null;
  const err = new Error('Wall-E built an empty provider message list before the model request.');
  err.code = 'WALLE_EMPTY_PROVIDER_MESSAGES';
  err.status = 400;
  err.providerError = {
    code: 'AI_PROVIDER_ERROR',
    type: 'request_invariant',
    severity: 'error',
    title: 'Wall-E request invariant failed',
    message: 'Wall-E prepared an empty model request. The current user turn was not present at the provider boundary, so no provider call was made.',
    userMessage: `${provider}${model ? ` (${model})` : ''}: Wall-E prepared an empty model request before calling the provider. Retry after the local fix is deployed; no provider request was sent.`,
    rawMessage: 'empty provider messages',
    status: 400,
    provider,
    model,
    providerId: context.providerId || null,
    registryId: context.registryId || null,
    routeLabel: context.routeLabel || null,
    connectionKind: context.connectionKind || null,
    actionLabel: null,
    actionUrl: null,
    createdAt: new Date().toISOString(),
  };
  return err;
}

function buildProviderMessagesForChat({
  historyMessages,
  currentMessage,
  attachmentBlocks,
  provider,
  model,
} = {}) {
  const current = String(currentMessage || '');
  const messages = [];
  for (const item of Array.isArray(historyMessages) ? historyMessages : []) {
    const normalized = _normalizeMessage(item);
    if (normalized) messages.push(normalized);
  }

  const last = messages[messages.length - 1];
  if (current && !_sameUserTurn(last, current)) {
    messages.push({ role: 'user', content: current });
  }

  if (Array.isArray(attachmentBlocks) && attachmentBlocks.length > 0) {
    let targetIndex = _lastUserIndex(messages, current);
    if (targetIndex < 0 && current) {
      messages.push({ role: 'user', content: current });
      targetIndex = messages.length - 1;
    }
    if (targetIndex >= 0) {
      const text = _contentText(messages[targetIndex].content) || current || 'Please inspect the attached file.';
      messages[targetIndex] = {
        role: 'user',
        content: [
          { type: 'text', text },
          ...attachmentBlocks,
        ],
      };
    }
  }

  if (messages.length === 0) {
    throw createEmptyProviderMessagesError({ provider, model });
  }

  return messages;
}

module.exports = {
  buildProviderMessagesForChat,
  createEmptyProviderMessagesError,
  _private: {
    contentText: _contentText,
    contentHasPayload: _contentHasPayload,
  },
};
