const PUBLIC_RUNTIME_ALLOWED_PATH = '/';

const PUBLIC_RUNTIME_ENTITY_FIELDS = {
  projects: [
    'id',
    'name',
    'slug',
    'description',
    'logo_url',
    'favicon_url',
    'og_image_url',
  ],
  tour_pages: [
    'id',
    'projectId',
    'environment',
    'source_key',
    'name',
    'slug',
    'sort_order',
    'background_image_url',
    'background_video_url',
    'background_audio_url',
    'background_loop',
    'requires_auth',
    'ui_schema_json',
  ],
  project_audio_tracks: [
    'id',
    'projectId',
    'environment',
    'source_key',
    'name',
    'slug',
    'url',
    'loop',
    'volume',
    'sort_order',
    'is_enabled',
  ],
};

const pickFields = (record, fields) => {
  if (!record || typeof record !== 'object') {
    return record;
  }

  // Convert Sequelize instance to plain object if needed
  const plainRecord =
    typeof record.get === 'function' ? record.get({ plain: true }) : record;

  return fields.reduce((acc, field) => {
    if (field in plainRecord && plainRecord[field] !== undefined) {
      acc[field] = plainRecord[field];
    }
    return acc;
  }, {});
};

const isPublicRuntimeReadRequest = (req) => {
  return req.isRuntimePublicRequest === true && req.method === 'GET';
};

const blockNonPublicRuntimeListEndpoints = (req, res, next) => {
  if (!isPublicRuntimeReadRequest(req)) {
    return next();
  }

  if (req.path !== PUBLIC_RUNTIME_ALLOWED_PATH) {
    return res.status(404).send({ message: 'Not found' });
  }

  if (req.query.filetype === 'csv') {
    return res.status(404).send({ message: 'Not found' });
  }

  return next();
};

const sanitizePublicRuntimeListResponse = (entityName) => {
  const fields = PUBLIC_RUNTIME_ENTITY_FIELDS[entityName] || [];

  return (req, res, next) => {
    if (
      !isPublicRuntimeReadRequest(req) ||
      req.path !== PUBLIC_RUNTIME_ALLOWED_PATH ||
      fields.length === 0
    ) {
      return next();
    }

    const originalSend = res.send.bind(res);

    res.send = (body) => {
      if (!body || typeof body !== 'object') {
        return originalSend(body);
      }

      if (!Array.isArray(body.rows)) {
        return originalSend(body);
      }

      const sanitizedRows = body.rows.map((row) => pickFields(row, fields));

      return originalSend({
        ...body,
        rows: sanitizedRows,
      });
    };

    return next();
  };
};

module.exports = {
  blockNonPublicRuntimeListEndpoints,
  sanitizePublicRuntimeListResponse,
};
