'use strict';

const crypto = require('crypto');
const brain = require('../brain');

const DEFAULT_ACCOUNT_ID = 'default';
const DEFAULT_ASSISTANT_APP_NAMES = ['claude', 'walle', 'wall-e'];

function normalizeAccountId(accountId) {
  return String(accountId || DEFAULT_ACCOUNT_ID);
}

function normalizeAppName(value) {
  return String(value || '').toLowerCase().replace(/[^a-z0-9]/g, '');
}

function hashPayload(value) {
  return crypto.createHash('sha1').update(String(value || '')).digest('hex');
}

function normalizeMessageRef(ref = {}) {
  const channel = String(ref.channel || '').trim();
  const conversationId = String(ref.conversationId || ref.target || '').trim();
  const messageId = String(ref.messageId || '').trim();
  if (!channel || !conversationId || !messageId) {
    throw new Error('Message ledger requires channel, conversationId, and messageId');
  }
  return {
    channel,
    accountId: normalizeAccountId(ref.accountId),
    conversationId,
    threadId: ref.threadId == null ? null : String(ref.threadId),
    messageId,
  };
}

function claimInboundMessage(ref = {}) {
  const normalized = normalizeMessageRef(ref);
  return brain.claimChannelMessageEvent({
    ...normalized,
    direction: ref.direction || 'inbound',
    origin: ref.origin || 'user',
    source: ref.source || null,
    deliveryId: ref.deliveryId || null,
    payloadHash: ref.payloadHash || hashPayload(ref.payload || ref.content || ''),
    metadata: ref.metadata,
  });
}

function recordOutboundDelivery(ref = {}) {
  const normalized = normalizeMessageRef(ref);
  return brain.recordChannelOutboundEvent({
    ...normalized,
    origin: ref.origin || 'assistant',
    source: ref.source || 'channel_outbound',
    deliveryId: ref.deliveryId || null,
    payloadHash: ref.payloadHash || hashPayload(ref.payload || ref.content || ref.deliveryId || ''),
    metadata: ref.metadata,
  });
}

function getMessageEvent(ref = {}) {
  const normalized = normalizeMessageRef(ref);
  return brain.getChannelMessageEvent(normalized);
}

function completeMessageEvent(id, updates = {}) {
  return brain.completeChannelMessageEvent(id, updates);
}

function releaseMessageEvent(id) {
  return brain.releaseChannelMessageEvent(id);
}

function isOutboundEvent(event) {
  const direction = String(event?.direction || '').toLowerCase();
  const status = String(event?.status || '').toLowerCase();
  const origin = String(event?.origin || '').toLowerCase();
  const source = String(event?.source || '').toLowerCase();
  return direction === 'outbound'
    || status === 'outbound'
    || origin === 'assistant'
    || origin === 'provider_app'
    || source.endsWith('_outbound')
    || source.includes(':outbound');
}

function isAssistantAppAttribution(appAttribution, assistantAppNames = DEFAULT_ASSISTANT_APP_NAMES) {
  const normalized = normalizeAppName(appAttribution);
  if (!normalized) return false;
  return assistantAppNames.map(normalizeAppName).includes(normalized);
}

function classifyInboundOrigin(ref = {}, opts = {}) {
  let event = null;
  try {
    event = getMessageEvent(ref);
  } catch {
    event = null;
  }
  if (isOutboundEvent(event)) {
    return { origin: 'assistant', outbound: true, reason: 'ledger', event };
  }
  if (isAssistantAppAttribution(opts.appAttribution, opts.assistantAppNames)) {
    if (opts.recordAttributed !== false) {
      const recorded = recordOutboundDelivery({
        ...ref,
        origin: 'provider_app',
        source: `${ref.channel || 'channel'}:app_attribution`,
        deliveryId: opts.deliveryId,
        metadata: {
          ...(opts.metadata || {}),
          appAttribution: opts.appAttribution,
        },
      });
      event = recorded.event || event;
    }
    return { origin: 'provider_app', outbound: true, reason: `app_attribution:${opts.appAttribution}`, event };
  }
  return { origin: 'user', outbound: false, reason: 'unknown', event };
}

module.exports = {
  DEFAULT_ACCOUNT_ID,
  DEFAULT_ASSISTANT_APP_NAMES,
  normalizeAccountId,
  hashPayload,
  claimInboundMessage,
  recordOutboundDelivery,
  getMessageEvent,
  completeMessageEvent,
  releaseMessageEvent,
  isOutboundEvent,
  isAssistantAppAttribution,
  classifyInboundOrigin,
};
