package db.migration;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.security.SecureRandom;
import java.sql.PreparedStatement;

import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.Context;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

public class V3__add_default_admin extends BaseJavaMigration {

    private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    private final SecureRandom random = new SecureRandom();

    /** different dictionaries used */
    private final String ALPHA_CAPS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private final String ALPHA = "abcdefghijklmnopqrstuvwxyz";
    private final String NUMERIC = "0123456789";
    private final String SPECIAL_CHARS = "!@#$%^&*_=+-/";

    /**
     * Method will generate random string based on the parameters
     * 
     * @param len the length of the random string
     * @param dic the dictionary used to generate the password
     * @return the random password
     */
    public String generatePassword(int len, String dic) {
        String result = "";
        for (int i = 0; i < len; i++) {
            int index = random.nextInt(dic.length());
            result += dic.charAt(index);
        }
        return result;
    }

    @Override
    public void migrate(final Context context) throws Exception {
        try (final PreparedStatement ps = context.getConnection()
                .prepareStatement("insert into users (user_id, name, password) values (0,?,?)")) {
            final String generatedPassword = generatePassword(60, ALPHA_CAPS + ALPHA + SPECIAL_CHARS);
            final BufferedWriter bw = new BufferedWriter(new FileWriter("gen-password.txt"));
            bw.write(generatedPassword);
            bw.write("\nPlease delete this file");
            bw.close();
            ps.setString(1, "admin");
            ps.setString(2, passwordEncoder.encode(generatedPassword));
            ps.execute();
        }

        try (final PreparedStatement ps = context.getConnection()
                .prepareStatement("insert into users_roles (user_id, role_id) values (1,0)")) {
            ps.execute();
        }
    }

}