import type { Core } from '@strapi/strapi';

/**
 * Single types that are safe for the public (unauthenticated) API role to
 * read. Only `find` exists on single-type controllers.
 */
const PUBLIC_READ_SINGLE_TYPES = ['organization', 'contact-info', 'home-page'];

/**
 * Collection types that make up the public content of the JDPH website and
 * are safe for the public API role to list/read. Deliberately excludes
 * `create`, `update` and `delete` — content is only ever written through the
 * admin panel.
 */
const PUBLIC_READ_COLLECTIONS = [
  'programme-area',
  'partner',
  'category',
  'news-article',
  'story',
  'team-member',
  'team-unit',
  'static-page',
  'job-opening',
  'event',
  'funding-opportunity',
  'procurement-notice',
];

async function ensurePermission(strapi: Core.Strapi, roleId: number, action: string) {
  const existing = await strapi.db.query('plugin::users-permissions.permission').findOne({
    where: { action, role: roleId },
  });
  if (!existing) {
    await strapi.db.query('plugin::users-permissions.permission').create({
      data: { action, role: roleId },
    });
  }
}

/**
 * Grants the public (unauthenticated) API role read access to the content
 * types the frontend needs, and nothing else. Contact Submission gets only
 * `create` so the future contact form can post to it, but no one can list or
 * read other people's submissions over the public API — that stays
 * admin-panel only. Idempotent: safe to run on every boot.
 */
async function setPublicPermissions(strapi: Core.Strapi) {
  const publicRole = await strapi.db
    .query('plugin::users-permissions.role')
    .findOne({ where: { type: 'public' } });

  if (!publicRole) {
    strapi.log.warn('setPublicPermissions: public role not found, skipping');
    return;
  }

  for (const uid of PUBLIC_READ_SINGLE_TYPES) {
    await ensurePermission(strapi, publicRole.id, `api::${uid}.${uid}.find`);
  }

  for (const uid of PUBLIC_READ_COLLECTIONS) {
    await ensurePermission(strapi, publicRole.id, `api::${uid}.${uid}.find`);
    await ensurePermission(strapi, publicRole.id, `api::${uid}.${uid}.findOne`);
  }

  await ensurePermission(
    strapi,
    publicRole.id,
    'api::contact-submission.contact-submission.create'
  );
}

export default {
  register() {},

  async bootstrap({ strapi }: { strapi: Core.Strapi }) {
    await setPublicPermissions(strapi);
  },
};
