const { interpolateTemplate } = require('./template');
const { createNotification } = require('@/services/notifications/service');

const modelNameFor = (entity) =>
  String(entity || '')
    .split(/[-_\s]/)
    .filter(Boolean)
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join('');

const getModel = (models, entityOrModelName) => {
  const modelName = models[entityOrModelName] ? entityOrModelName : modelNameFor(entityOrModelName);
  const Model = models[modelName];
  if (!Model) throw new Error(`Model not available for automation action: ${entityOrModelName}`);
  return Model;
};

const buildContext = (event) => ({
  ...(event && typeof event.toObject === 'function' ? event.toObject() : event),
  id: event?._id,
});

const withOwnership = (event, payload) => ({
  tenant: event.tenant,
  createdBy: event.actor,
  assignedTo: event.actor,
  ...payload,
});

const executeAutomationAction = async ({ action, event, models, providers }) => {
  const config = interpolateTemplate(action.config || {}, buildContext(event));
  let result;

  switch (action.type) {
    case 'create_record': {
      const Model = getModel(models, config.entity || config.model);
      const record = await Model.create(withOwnership(event, config.data || {}));
      result = { type: action.type, entity: config.entity || config.model, record };
      break;
    }
    case 'update_record': {
      const entity = config.entity || event.entity;
      const Model = getModel(models, entity);
      const id = config.id || event.entityId;
      const record = await Model.findOneAndUpdate(
        { _id: id, ...(event.tenant ? { tenant: event.tenant } : {}) },
        config.data || {},
        { new: true, runValidators: true }
      ).exec();
      result = { type: action.type, entity, record };
      break;
    }
    case 'send_email': {
      const providerResult = await providers.resend.sendEmail(config);
      result = { type: action.type, provider: 'resend', result: providerResult };
      break;
    }
    case 'send_whatsapp': {
      const providerResult = await providers.meta.request('sendWhatsApp', config);
      result = { type: action.type, provider: 'meta', result: providerResult };
      break;
    }
    case 'generate_content': {
      const providerName = config.provider || 'kimi';
      const providerResult = await providers[providerName].request('generateContent', config);
      let asset = null;
      if (models.ContentAsset) {
        asset = await models.ContentAsset.create(
          withOwnership(event, {
            title: config.title || 'Automation content',
            type: config.contentType || 'email',
            prompt: config.prompt,
            content: providerResult.content || providerResult.message,
            provider: providerName,
            brandContext: config.brandContext,
          })
        );
      }
      result = { type: action.type, provider: providerName, result: providerResult, asset };
      break;
    }
    case 'create_task': {
      const record = await getModel(models, 'Task').create(
        withOwnership(event, {
          relatedTo: { entityType: event.entity, entityId: event.entityId },
          ...config,
        })
      );
      result = { type: action.type, record };
      break;
    }
    case 'schedule_social_post': {
      const record = await getModel(models, 'SocialPost').create(withOwnership(event, config));
      result = { type: action.type, record };
      break;
    }
    default:
      throw new Error(`Unsupported automation action: ${action.type}`);
  }

  if (event.tenant && event.actor) {
    await createNotification({
      tenantId: event.tenant,
      actorId: event.actor,
      recipientId: event.actor,
      type: `automation.action.${action.type}`,
      title: `Automation action completed`,
      message: `${action.type} finished for ${event.type || event.entity}.`,
      severity: ['create_record', 'update_record'].includes(action.type) ? 'success' : 'info',
      entityType: event.entity,
      entityId: event.entityId,
      actionUrl: '/automations',
      eventKey: `automation-action:${event._id}:${action.type}:${config.title || config.model || ''}`,
      channels: ['in_app'],
    });
  }

  return result;
};

module.exports = {
  executeAutomationAction,
  modelNameFor,
};
