import fs from "fs";
import handleNodemailer from "../../backend/handleNodemailer";
import path from "path";
import addMariadbUser from "../../backend/addMariadbUser";
import varDatabaseDbHandler from "../../backend/varDatabaseDbHandler";
import encrypt from "../../dsql/encrypt";
import addDbEntry from "../../backend/db/addDbEntry";
import loginSocialUser from "./loginSocialUser";
import {
    APILoginFunctionReturn,
    HandleSocialDbFunctionParams,
} from "../../../types";

/**
 * # Handle Social DB
 */
export default async function handleSocialDb({
    database,
    social_id,
    email,
    social_platform,
    payload,
    invitation,
    supEmail,
    additionalFields,
    debug,
}: HandleSocialDbFunctionParams): Promise<APILoginFunctionReturn> {
    try {
        const finalDbName = global.DSQL_USE_LOCAL
            ? undefined
            : database
            ? database
            : "datasquirel";
        const dbAppend = global.DSQL_USE_LOCAL ? "" : `${finalDbName}.`;

        const existingSocialIdUserQuery = `SELECT * FROM ${dbAppend}users WHERE social_id = ? AND social_login='1' AND social_platform = ? `;
        const existingSocialIdUserValues = [
            social_id.toString(),
            social_platform,
        ];

        if (debug) {
            console.log(
                "handleSocialDb:existingSocialIdUserQuery",
                existingSocialIdUserQuery
            );
            console.log(
                "handleSocialDb:existingSocialIdUserValues",
                existingSocialIdUserValues
            );
        }

        let existingSocialIdUser = await varDatabaseDbHandler({
            database: finalDbName,
            queryString: existingSocialIdUserQuery,
            queryValuesArray: existingSocialIdUserValues,
            debug,
        });

        if (debug) {
            console.log(
                "handleSocialDb:existingSocialIdUser",
                existingSocialIdUser
            );
        }

        if (existingSocialIdUser?.[0]) {
            return await loginSocialUser({
                user: existingSocialIdUser[0],
                social_platform,
                invitation,
                database: finalDbName,
                additionalFields,
                debug,
            });
        }

        const finalEmail = email ? email : supEmail ? supEmail : null;

        if (!finalEmail) {
            return {
                success: false,
                payload: null,
                msg: "No Email Present",
            };
        }

        const existingEmailOnlyQuery = `SELECT * FROM ${dbAppend}users WHERE email='${finalEmail}'`;

        if (debug) {
            console.log(
                "handleSocialDb:existingEmailOnlyQuery",
                existingEmailOnlyQuery
            );
        }

        let existingEmailOnly = await varDatabaseDbHandler({
            database: finalDbName,
            queryString: existingEmailOnlyQuery,
            debug,
        });

        if (debug) {
            console.log("handleSocialDb:existingEmailOnly", existingEmailOnly);
        }

        if (existingEmailOnly && existingEmailOnly[0]) {
            return {
                success: false,
                payload: null,
                msg: "This Email is already taken",
            };
        }

        const foundUserQuery = `SELECT * FROM ${dbAppend}users WHERE email=? AND social_login='1' AND social_platform=? AND social_id=?`;
        const foundUserQueryValues = [finalEmail, social_platform, social_id];

        const foundUser = await varDatabaseDbHandler({
            database: finalDbName,
            queryString: foundUserQuery,
            queryValuesArray: foundUserQueryValues,
            debug,
        });

        if (foundUser && foundUser[0]) {
            return await loginSocialUser({
                user: payload,
                social_platform,
                invitation,
                database: finalDbName,
                additionalFields,
                debug,
            });
        }

        const socialHashedPassword = encrypt({
            data: social_id.toString(),
        });

        const data: { [k: string]: any } = {
            social_login: "1",
            verification_status: supEmail ? "0" : "1",
            password: socialHashedPassword,
        };

        Object.keys(payload).forEach((key) => {
            data[key] = payload[key];
        });

        const newUser = await addDbEntry({
            dbContext: finalDbName ? "Dsql User" : undefined,
            paradigm: finalDbName ? "Full Access" : undefined,
            dbFullName: finalDbName,
            tableName: "users",
            duplicateColumnName: "email",
            duplicateColumnValue: finalEmail,
            data: {
                ...data,
                email: finalEmail,
            },
        });

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

            const newUserQueriedQuery = `SELECT * FROM ${dbAppend}users WHERE id='${newUser.insertId}'`;

            const newUserQueried = await varDatabaseDbHandler({
                database: finalDbName,
                queryString: newUserQueriedQuery,
                debug,
            });

            if (!newUserQueried || !newUserQueried[0])
                return {
                    success: false,
                    payload: null,
                    msg: "User Insertion Failed!",
                };

            if (supEmail && database?.match(/^datasquirel$/)) {
                /**
                 * Send email Verification
                 *
                 * @description Send verification email to newly created agent
                 */
                let generatedToken = encrypt({
                    data: JSON.stringify({
                        id: newUser.insertId,
                        email: supEmail,
                        dateCode: Date.now(),
                    }),
                });

                handleNodemailer({
                    to: supEmail,
                    subject: "Verify Email Address",
                    text: "Please click the link to verify your email address",
                    html: fs
                        .readFileSync(
                            "./email/send-email-verification-link.html",
                            "utf8"
                        )
                        .replace(/{{host}}/, process.env.DSQL_HOST || "")
                        .replace(/{{token}}/, generatedToken || ""),
                }).then(() => {});
            }

            const STATIC_ROOT = process.env.DSQL_STATIC_SERVER_DIR;

            if (!STATIC_ROOT) {
                console.log("Static File ENV not Found!");
                return {
                    success: false,
                    payload: null,
                    msg: "Static File ENV not Found!",
                };
            }

            /**
             * Create new user folder and file
             *
             * @description Create new user folder and file
             */
            if (!database || database?.match(/^datasquirel$/)) {
                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);
                fs.mkdirSync(newUserMediaFolderPath);

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

            return await loginSocialUser({
                user: newUserQueried[0],
                social_platform,
                invitation,
                database: finalDbName,
                additionalFields,
                debug,
            });
        } else {
            console.log(
                "Social User Failed to insert in 'handleSocialDb.ts' backend function =>",
                newUser
            );

            return {
                success: false,
                payload: null,
                msg: "Social User Failed to insert in 'handleSocialDb.ts' backend function",
            };
        }
    } catch (error: any) {
        console.log(
            "ERROR in 'handleSocialDb.ts' backend function =>",
            error.message
        );

        return {
            success: false,
            payload: null,
            msg: error.message,
        };
    }
}
