import path from "path";
require("dotenv").config({ path: "../../../.env" });
import fs from "fs";
import { execSync } from "child_process";
import EJSON from "../../../utils/ejson";
import DB_HANDLER from "../../../utils/backend/global-db/DB_HANDLER";
import addDbEntry from "../../../functions/backend/db/addDbEntry";
import addMariadbUser from "../../../functions/backend/addMariadbUser";
import updateDbEntry from "../../../functions/backend/db/updateDbEntry";
import hashPassword from "../../../functions/dsql/hashPassword";

const tmpDir = process.argv[process.argv.length - 1];

/**
 * # Create New User
 */
async function createUser() {
    /**
     * Validate Form
     *
     * @description Check if request body is valid
     */
    try {
        const isTmpDir = Boolean(tmpDir?.match(/\.json$/));
        const targetPath = isTmpDir
            ? path.resolve(process.cwd(), tmpDir)
            : path.resolve(__dirname, "./new-user.json");

        const userObj = EJSON.parse(fs.readFileSync(targetPath, "utf-8"));

        if (typeof userObj !== "object" || Array.isArray(userObj))
            throw new Error("User Object Invalid!");

        const ROOT_DIR = path.resolve(__dirname, "../../../");

        /**
         * Validate Form
         *
         * @description Check if request body is valid
         */
        const first_name = userObj.first_name;
        const last_name = userObj.last_name;
        const email = userObj.email;
        const password = userObj.password;
        const username = userObj.username;

        if (!email?.match(/.*@.*\..*/)) return false;

        if (
            !first_name?.match(/^[a-zA-Z]+$/) ||
            !last_name?.match(/^[a-zA-Z]+$/)
        )
            return false;

        if (password?.match(/ /)) return false;

        if (username?.match(/ /)) return false;

        let hashedPassword = hashPassword({
            encryptionKey: process.env.DSQL_ENCRYPTION_PASSWORD || "",
            password: password,
        });

        let existingUser = await DB_HANDLER(
            `SELECT * FROM users WHERE email='${email}'`
        );

        if (existingUser?.[0]) {
            console.log("User Exists");
            return false;
        }

        const newUser = await addDbEntry({
            dbFullName: "datasquirel",
            tableName: "users",
            data: { ...userObj, password: hashedPassword },
        });

        if (!newUser?.insertId) return false;

        /**
         * Add a Mariadb User for this User
         */
        await addMariadbUser({ userId: newUser.insertId });

        const STATIC_ROOT = process.env.DSQL_STATIC_SERVER_DIR;

        if (!STATIC_ROOT) {
            console.log("Static File ENV not Found!");
            throw new Error("No Static Path");
        }

        /**
         * Create new user folder and file
         *
         * @description Create new user folder and file
         */
        let newUserSchemaFolderPath = `${process.env.DSQL_USER_DB_SCHEMA_PATH}/user-${newUser.insertId}`;
        let newUserMediaFolderPath = path.join(
            STATIC_ROOT,
            `images/user-images/user-${newUser.insertId}`
        );

        fs.mkdirSync(newUserSchemaFolderPath, { recursive: true });
        fs.mkdirSync(newUserMediaFolderPath, { recursive: true });

        fs.writeFileSync(
            `${newUserSchemaFolderPath}/main.json`,
            JSON.stringify([]),
            "utf8"
        );

        const imageBasePath = path.join(
            STATIC_ROOT,
            `images/user-images/user-${newUser.insertId}`
        );

        if (!fs.existsSync(imageBasePath)) {
            fs.mkdirSync(imageBasePath, { recursive: true });
        }

        let imagePath = path.join(
            STATIC_ROOT,
            `images/user-images/user-${newUser.insertId}/user-${newUser.insertId}-profile.jpg`
        );

        let imageThumbnailPath = path.join(
            STATIC_ROOT,
            `images/user-images/user-${newUser.insertId}/user-${newUser.insertId}-profile-thumbnail.jpg`
        );

        let prodImageUrl = imagePath.replace(
            STATIC_ROOT,
            process.env.DSQL_STATIC_HOST || ""
        );
        let prodImageThumbnailUrl = imageThumbnailPath.replace(
            STATIC_ROOT,
            process.env.DSQL_STATIC_HOST || ""
        );

        fs.copyFileSync(
            path.join(ROOT_DIR, "/public/images/user-preset.png"),
            imagePath
        );
        fs.copyFileSync(
            path.join(ROOT_DIR, "/public/images/user-preset-thumbnail.png"),
            imageThumbnailPath
        );

        execSync(`chmod 644 ${imagePath} ${imageThumbnailPath}`);

        const updateImages = await updateDbEntry({
            dbFullName: "datasquirel",
            tableName: "users",
            identifierColumnName: "id",
            identifierValue: newUser.insertId,
            data: {
                image: prodImageUrl,
                image_thumbnail: prodImageThumbnailUrl,
            },
        });

        if (isTmpDir) {
            try {
                fs.unlinkSync(path.resolve(process.cwd(), tmpDir));
            } catch (error) {}
        }

        return true;
    } catch (error: any) {
        global.ERROR_CALLBACK?.(`Error Creating User`, error as Error);
        return false;
    }
}

createUser().then((res) => {
    if (res) {
        console.log("User Creation Success!!!");
    } else {
        console.log("User Creation Failed!");
    }
    process.exit();
});