import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.apache.commons.lang3.RandomStringUtils;
import org.bson.Document;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MoviesGenerator {

    //router address
    private static final String MONGO_DB_URL = "mongodb://192.168.144.132:27033/";
    private static final String DB_NAME = "videodb";
    private static final String COLLECTION_NAME = "movies";

    private static final Random random = new Random();

    public static void main(String[] args) {
        MongoDatabase onlineSchoolDb = connectToMongoDB(MONGO_DB_URL, DB_NAME);
        generateMovies(10000, onlineSchoolDb, COLLECTION_NAME);
        generateUsers(10000, onlineSchoolDb);
    }

    private static MongoDatabase connectToMongoDB(String url, String dbName) {
        MongoClient mongoClient = MongoClients.create(MONGO_DB_URL);
        return mongoClient.getDatabase(dbName);
    }

    private static void generateMovies(int numberOfMovies, MongoDatabase database, String collectionName) {
        MongoCollection<Document> collection = database.getCollection(collectionName);

        List<Document> documents = new ArrayList<>();
        System.out.println("Generating " + numberOfMovies + " movies");
        for (int movieIndex = 0; movieIndex < numberOfMovies; movieIndex++) {
            Document document = new Document();
            document.append("title", generateName())
                    .append("directors", generateDirectorNames())
                    .append("rating", generateRating())
                    .append("cast", generateCast());
            documents.add(document);
        }

        collection.insertMany(documents);

        System.out.println("Finished generating movies");
    }


    private static List<String> generateDirectorNames() {
        int numberOfDirectors = random.nextInt(3) + 1;
        List<String> directors = new ArrayList<>(numberOfDirectors);

        for (int i = 0; i < numberOfDirectors; i++) {
            String firstName = generateName();
            String lastName = generateName();
            directors.add(firstName + " " + lastName);
        }

        return directors;
    }


    private static int generateYear() {
        return random.nextInt(119) + 1900;
    }


    private static float generateRating() {
        return random.nextFloat() * 10.0f;
    }


    private static List<String> generateCast() {
        int numberOfActors = random.nextInt(20) + 10;
        List<String> actors = new ArrayList<>(numberOfActors);

        for (int i = 0; i < numberOfActors; i++) {
            String firstName = generateName();
            String lastName = generateName();
            actors.add(firstName + " " + lastName);
        }

        return actors;
    }

    private static String generateName() {
        StringBuilder name = new StringBuilder();

        name.append(RandomStringUtils.randomAlphabetic(1).toUpperCase());
        name.append(RandomStringUtils.randomAlphabetic(5, 10).toLowerCase());

        return name.toString();
    }

    private static void generateUsers(int numberOfUsers, MongoDatabase database) {
        MongoCollection<Document> collection = database.getCollection("users");
        List<Document> userDocs = new ArrayList<>();
        String[] sampleMovies = {"Inside out", "Aladdin", "The Lion King", "Matrix", "Inception"};

        for (int i = 0; i < numberOfUsers; i++) {
            Document user = new Document()
                    .append("user_name", "User_" + RandomStringUtils.randomAlphabetic(5))
                    .append("watched_movies", List.of(
                            sampleMovies[random.nextInt(sampleMovies.length)],
                            sampleMovies[random.nextInt(sampleMovies.length)]
                    ))
                    .append("subscription_month", random.nextInt(12) + 1);
            userDocs.add(user);

            if (i % 1000 == 0) {
                collection.insertMany(userDocs);
                userDocs.clear();
            }
        }
        System.out.println("Finished generating users with Hashed Sharding.");
    }
}
