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

const SALT_ROUNDS = 10;

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('Create an admin (active) user from CLI');
    console.log('');
    console.log('Usage:');
    console.log('  npm run create:admin -- --username <username> --password <password> --fname <firstName> --lname <lastName> --email <email> --phone <phone> [--mname <middleName>] [--gender <gender>] [--group <groupName>]');
    console.log('');
    console.log('Options:');
    console.log('  --username   Username (required, must be unique)');
    console.log('  --password   Plaintext password (required, min 8 chars)');
    console.log('  --fname      First name (required)');
    console.log('  --lname      Last name (required)');
    console.log('  --email      Email address (required)');
    console.log('  --phone      Phone number (required)');
    console.log('  --mname      Middle name (optional, defaults to empty)');
    console.log('  --gender     Gender (optional, defaults to "unspecified")');
    console.log('  --group      Group name to assign user to (optional)');
    console.log('  --help       Show this help text');
};

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

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

    const required = ['username', 'password', 'fname', 'lname', 'email', 'phone'];
    const missing = required.filter(k => typeof args[k] !== 'string' || args[k].trim().length === 0);

    if (missing.length > 0) {
        console.error(`Missing required arguments: ${missing.map(k => '--' + k).join(', ')}`);
        console.error('');
        printHelp();
        process.exitCode = 1;
        return;
    }

    if (args.password.length < 8) {
        console.error('Password must be at least 8 characters.');
        process.exitCode = 1;
        return;
    }

    const username = args.username.trim().toLowerCase();

    const existing = await models.User.findOne({ where: { username }, attributes: ['id'] });
    if (existing) {
        console.error(`User with username "${username}" already exists.`);
        process.exitCode = 1;
        return;
    }

    const hashedPassword = await bcrypt.hash(args.password, SALT_ROUNDS);

    const user = await models.User.create({
        fname: args.fname.trim(),
        mname: (args.mname || '').trim(),
        lname: args.lname.trim(),
        gender: (args.gender || 'unspecified').trim(),
        username,
        password: hashedPassword,
        email: args.email.trim(),
        phone: args.phone.trim(),
        status: 'active'
    });

    console.log(`Admin user created: ${user.username} (id: ${user.id})`);

    if (typeof args.group === 'string' && args.group.trim().length > 0) {
        const group = await models.Group.findOne({ where: { name: args.group.trim() }, attributes: ['id', 'name'] });
        if (!group) {
            console.warn(`Warning: Group "${args.group.trim()}" not found. User created but not assigned to any group.`);
        } else {
            await user.addGroup(group);
            console.log(`User assigned to group "${group.name}" (id: ${group.id})`);
        }
    } else {
        console.log('No --group specified. Assign the user to a group via the application to grant permissions.');
    }
};

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