import { hash } from '@node-rs/argon2';
import { Connection } from 'typeorm';
import { Factory, Seeder } from 'typeorm-seeding';
import * as uuid from 'uuid';
import { CreatePermission } from '../models/actions/create/CreatePermission';
import { CreateUserGroup } from '../models/actions/create/CreateUserGroup';
import { Permission } from '../models/entities/Permission';
import { User } from '../models/entities/User';
import { UserGroup } from '../models/entities/UserGroup';
import { PermissionAction } from '../models/enums/PermissionAction';
import { PermissionTarget } from '../models/enums/PermissionTargets';
/**
 * Seeds a admin group with a demo user into the database for initial setup and auto recovery.
 * We know that the naming isn't perfectly fitting. Feel free to change it.
 */
export default class SeedUsers implements Seeder {
    public async run(factory: Factory, connection: Connection): Promise<any> {
        let adminGroup: UserGroup = await this.createAdminGroup(connection);
        await this.createUser(connection, adminGroup);
        await this.createPermissions(connection, adminGroup.id);
    }

    public async createAdminGroup(connection: Connection) {
        let adminGroup = new CreateUserGroup();
        adminGroup.name = "ADMINS";
        adminGroup.description = "Have all possible permissions";
        return await connection.getRepository(UserGroup).save(await adminGroup.toEntity());
    }

    public async createUser(connection: Connection, group: UserGroup) {
        let initialUser = new User();
        initialUser.firstname = "demo";
        initialUser.lastname = "demo";
        initialUser.username = "demo";
        initialUser.uuid = uuid.v4();
        initialUser.password = await hash("demo" + initialUser.uuid);
        initialUser.email = "demo@dev.lauf-fuer-kaya.de"
        initialUser.groups = [group];
        return await connection.getRepository(User).save(initialUser);
    }

    public async createPermissions(connection: Connection, principal: number) {
        let repo = await connection.getRepository(Permission);
        for (let target in PermissionTarget) {
            for (let action in PermissionAction) {
                let permission = new CreatePermission;
                permission.target = <PermissionTarget>target;
                permission.action = <PermissionAction>action;
                permission.principal = principal;
                await repo.save(await permission.toEntity());
            }
        }
    }
}