'use strict';

function _messageHasPayload(message) {
  if (!message || typeof message !== 'object') return false;
  const role = String(message.role || '').trim();
  if (role !== 'user' && role !== 'assistant') return false;
  const content = message.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 _emptyMessagesError({ provider, model } = {}) {
  const providerLabel = provider || 'unknown';
  const err = new Error('Provider request aborted: messages must contain at least one non-empty chat message.');
  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 refused to send an empty message list to the provider.',
    userMessage: `${providerLabel}${model ? ` (${model})` : ''}: Wall-E refused to send an empty model request. No provider call was made.`,
    rawMessage: 'empty provider messages',
    status: 400,
    provider: provider || null,
    model: model || null,
    providerId: null,
    registryId: null,
    routeLabel: null,
    connectionKind: null,
    actionLabel: null,
    actionUrl: null,
    createdAt: new Date().toISOString(),
  };
  return err;
}

function assertProviderMessages(messages, context = {}) {
  if (!Array.isArray(messages) || !messages.some(_messageHasPayload)) {
    throw _emptyMessagesError(context);
  }
}

function withProviderMessageGuard(provider) {
  if (!provider || provider.__walleMessageGuarded === true) return provider;
  const guarded = { ...provider, __walleMessageGuarded: true };
  if (typeof provider.chat === 'function') {
    guarded.chat = async function guardedChat(opts = {}) {
      assertProviderMessages(opts.messages, {
        provider: opts.provider || provider.type,
        model: opts.model,
      });
      return provider.chat.call(provider, opts);
    };
  }
  if (typeof provider.chatStream === 'function') {
    guarded.chatStream = async function* guardedChatStream(opts = {}) {
      assertProviderMessages(opts.messages, {
        provider: opts.provider || provider.type,
        model: opts.model,
      });
      yield* provider.chatStream.call(provider, opts);
    };
  }
  return guarded;
}

module.exports = {
  assertProviderMessages,
  withProviderMessageGuard,
  _private: { messageHasPayload: _messageHasPayload },
};
