const { v4: uuid } = require("uuid");

module.exports = {
  async up(queryInterface) {
    const createdAt = new Date();
    const updatedAt = new Date();
    const ids = new Map();

    function getId(key) {
      if (!ids.has(key)) {
        ids.set(key, uuid());
      }

      return ids.get(key);
    }

    function permissionRows(entity) {
      const name = entity.toUpperCase();

      return [
        { id: getId(`CREATE_${name}`), name: `CREATE_${name}`, createdAt, updatedAt },
        { id: getId(`READ_${name}`), name: `READ_${name}`, createdAt, updatedAt },
        { id: getId(`UPDATE_${name}`), name: `UPDATE_${name}`, createdAt, updatedAt },
        { id: getId(`DELETE_${name}`), name: `DELETE_${name}`, createdAt, updatedAt },
      ];
    }

    const roles = [
      { key: "Administrator", name: "Administrator" },
      { key: "WorkspaceOwner", name: "Workspace Owner" },
      { key: "Coach", name: "Coach" },
      { key: "Assistant", name: "Assistant" },
      { key: "Client", name: "Client" },
      { key: "Public", name: "Public" },
    ];

    const entities = [
      "users",
      "roles",
      "permissions",
      "clients",
      "sessions",
      "action_items",
      "resources",
      "packages",
      "testimonials",
      "prep_briefs",
      "intake_leads",
      "coaching",
    ];

    const permissions = entities.flatMap(permissionRows);
    permissions.push({ id: getId("READ_API_DOCS"), name: "READ_API_DOCS", createdAt, updatedAt });
    permissions.push({ id: getId("CREATE_SEARCH"), name: "CREATE_SEARCH", createdAt, updatedAt });

    await queryInterface.bulkInsert(
      "roles",
      roles.map((role) => ({
        id: getId(role.key),
        name: role.name,
        createdAt,
        updatedAt,
      })),
    );

    await queryInterface.bulkInsert("permissions", permissions);

    const rolePermissions = [];

    function grant(roleKey, permissionNames) {
      for (const permissionName of permissionNames) {
        rolePermissions.push({
          createdAt,
          updatedAt,
          roles_permissionsId: getId(roleKey),
          permissionId: getId(permissionName),
        });
      }
    }

    const allPermissionNames = permissions.map((permission) => permission.name);
    grant("Administrator", allPermissionNames);
    grant("WorkspaceOwner", allPermissionNames);

    const coachPermissionNames = allPermissionNames.filter((name) => {
      return !name.includes("_ROLES") && !name.includes("_PERMISSIONS");
    });
    grant("Coach", coachPermissionNames);

    grant("Assistant", [
      "READ_CLIENTS",
      "UPDATE_CLIENTS",
      "READ_SESSIONS",
      "CREATE_SESSIONS",
      "UPDATE_SESSIONS",
      "READ_ACTION_ITEMS",
      "UPDATE_ACTION_ITEMS",
      "READ_RESOURCES",
      "CREATE_RESOURCES",
      "UPDATE_RESOURCES",
      "READ_PACKAGES",
      "READ_PREP_BRIEFS",
      "READ_INTAKE_LEADS",
      "UPDATE_INTAKE_LEADS",
      "READ_COACHING",
      "CREATE_COACHING",
      "CREATE_SEARCH",
    ]);

    grant("Client", [
      "READ_CLIENTS",
      "READ_SESSIONS",
      "READ_ACTION_ITEMS",
      "UPDATE_ACTION_ITEMS",
      "READ_RESOURCES",
      "READ_PACKAGES",
      "READ_COACHING",
    ]);

    grant("Public", ["CREATE_INTAKE_LEADS"]);

    await queryInterface.bulkInsert("rolesPermissionsPermissions", rolePermissions);

    await queryInterface.sequelize.query(
      `UPDATE users SET "app_roleId" = '${getId("Administrator")}' WHERE email = 'admin@coaching-demo.invalid';`,
    );
    await queryInterface.sequelize.query(
      `UPDATE users SET "app_roleId" = '${getId("Coach")}' WHERE email = 'coach@coaching-demo.invalid';`,
    );
    await queryInterface.sequelize.query(
      `UPDATE users SET "app_roleId" = '${getId("Client")}' WHERE email = 'client@coaching-demo.invalid';`,
    );
  },

  async down(queryInterface) {
    await queryInterface.bulkDelete("rolesPermissionsPermissions", null, {});
    await queryInterface.bulkDelete("permissions", null, {});
    await queryInterface.bulkDelete("roles", null, {});
  },
};
