const sequelize = require('../config/db.js');
const models = require('../models/index.js');
const GroupModules = require('../models/group_modules.js');

const parseArgs = (argv) => {
    const args = {};
    for (let i = 2; i < argv.length; i += 1) {
        const arg = argv[i];
        if (!arg.startsWith('--')) continue;
        const key = arg.slice(2);
        const value = argv[i + 1];
        if (!value || value.startsWith('--')) {
            args[key] = true;
            continue;
        }
        args[key] = value;
        i += 1;
    }
    return args;
};

const printHelp = () => {
    console.log('Grant full CRUD access to a group on all (or a specific) module.');
    console.log('');
    console.log('Usage:');
    console.log('  npm run grant:access -- --group <groupName> [--module <moduleName>]');
    console.log('');
    console.log('Options:');
    console.log('  --group    Group name to grant access to (required)');
    console.log('  --module   Specific module name to grant access on (optional; defaults to ALL modules)');
    console.log('  --help     Show this help text');
};

const main = async () => {
    const args = parseArgs(process.argv);

    if (args.help) {
        printHelp();
        return;
    }

    if (typeof args.group !== 'string' || !args.group.trim()) {
        console.error('--group is required.');
        console.error('');
        printHelp();
        process.exitCode = 1;
        return;
    }

    const groupName = args.group.trim();
    const moduleName = typeof args.module === 'string' ? args.module.trim() : null;

    const group = await models.Group.findOne({ where: { name: groupName }, attributes: ['id', 'name'] });
    if (!group) {
        console.error(`Group "${groupName}" not found.`);
        process.exitCode = 1;
        return;
    }

    const moduleWhere = moduleName ? { name: moduleName } : {};
    const modules = await models.Module.findAll({ where: moduleWhere, attributes: ['id', 'name'] });

    if (modules.length === 0) {
        console.error(moduleName ? `Module "${moduleName}" not found.` : 'No modules found in the database.');
        process.exitCode = 1;
        return;
    }

    const now = new Date();
    let updated = 0;
    let created = 0;

    for (const mod of modules) {
        const [record, wasCreated] = await GroupModules.findOrCreate({
            where: { groupId: group.id, moduleId: mod.id },
            defaults: {
                groupId: group.id,
                moduleId: mod.id,
                create: true,
                read: true,
                update: true,
                delete: true,
                createdAt: now,
                updatedAt: now
            }
        });

        if (!wasCreated) {
            await record.update({ create: true, read: true, update: true, delete: true, updatedAt: now });
            updated += 1;
        } else {
            created += 1;
        }

        console.log(`  [${wasCreated ? 'CREATED' : 'UPDATED'}] group "${group.name}" → module "${mod.name}" (CRUD: true/true/true/true)`);
    }

    console.log('');
    console.log(`Done. Created: ${created}, Updated: ${updated}`);
    console.log(`Re-login as "${groupName}" users for the new permissions to take effect.`);
};

main()
    .catch((err) => {
        console.error('Failed:', err?.message || String(err));
        process.exitCode = 1;
    })
    .finally(async () => {
        try {
            await sequelize.close();
        } catch (_) {
            // Best effort.
        }
    });
