import {
    logError,
    logInfo,
    readConfig,
    uploadMediaFromEvent,
    convertMsgType
} from './utils.js';

import {
    appendUserPictures,
    checkForMutualLike,
    fullEraseUser,
    getAmountOfUserPictures,
    setUserLanguage,
    getUserLanguage,
    findCity,
    db,
    setUserState,
    selectProfilesForUser,
    setUserCurrentlyViewingProfile,
    getProfileInfo,
    getAllLikesForUser,
    markLikeAsRead,
    getCountryNameByID,
    getCityNameByID
} from "./db.js";

import fs from 'fs';

const config = readConfig();
const maxAmountOfPhotoesPerUser = config.maxAmountOfPhotoesPerUser;


import { I18n } from "i18n-js";
const i18n = new I18n({
    en: JSON.parse(fs.readFileSync("./translations/en.json")),
    ru: JSON.parse(fs.readFileSync("./translations/ru.json"))
});

i18n.defaultLocale = "en";

const requiresLengths = {
    "location": 32,
    "description": 512,
    "name": 32
};

const processRequest = async (client, roomId, question, answer, nextQuestion) => {

    let preferredLanguage = await getUserLanguage(roomId);
    if (!preferredLanguage) preferredLanguage = i18n.defaultLocale;
    i18n.locale = preferredLanguage;

    if (answer.length > requiresLengths[question]) {
        await client.sendText(roomId, i18n.t(["errors", "toobig"]));
        return;
    }
    let q = question.split("_")
    if (q[1] == "u")
        await db.query(`UPDATE users SET ${q[0]} = $1 WHERE room_id = $2`, [answer, roomId]);
    else
        await db.query(`UPDATE users SET ${question} = $1 WHERE room_id = $2`, [answer, roomId]);
    await client.sendText(roomId, i18n.t(["general", "setopt"], { opt: answer }));
    if (nextQuestion == "menu")
        await client.sendText(roomId, i18n.t(["general", "menu"]));
    else
        await client.sendText(roomId, i18n.t(["setup", nextQuestion]));

    setUserState(roomId, nextQuestion);
};

const showProfile = async (client, roomId, chosenProfile) => {
    chosenProfile.country = await getCountryNameByID(chosenProfile.location);
    chosenProfile.city = await getCityNameByID(chosenProfile.location);

    let message =
        `${chosenProfile.country}, ${chosenProfile.city}.
${chosenProfile.name}, ${chosenProfile.sex == 'm' ? 'male' : 'female'}, ${chosenProfile.age}.
${chosenProfile.description}`;

    await client.sendText(roomId, message);

    if (chosenProfile.media) {
        for (let media of chosenProfile.media) {
            let msgtype;
            if (media.type == 'p') {
                msgtype = "m.image";
            } else if (media.type == 'v') {
                msgtype = "m.video";
            }
            await client.sendMessage(roomId, {
                msgtype: msgtype,
                body: "Profile media",
                url: media.url
            });
        }
    }
}

const showRandomProfileToUser = async (client, roomId) => {
    let preferredLanguage = await getUserLanguage(roomId);
    if (!preferredLanguage) preferredLanguage = i18n.defaultLocale;
    i18n.locale = preferredLanguage;

    let chosenProfile = await selectProfilesForUser(roomId);

    if (!chosenProfile) {
        await client.sendText(roomId, i18n.t(["errors", "noprofiles"]));
        return;
    }

    await showProfile(client, roomId, chosenProfile);

    await setUserCurrentlyViewingProfile(roomId, chosenProfile.room_id);
    await client.sendText(roomId, i18n.t(["general", "rate"]));
};

const showProfileToUser = async (client, roomId, profileId) => {
    let preferredLanguage = await getUserLanguage(roomId);
    if (!preferredLanguage) preferredLanguage = i18n.defaultLocale;
    i18n.locale = preferredLanguage;

    let profileInfo = await getProfileInfo(profileId);

    await client.sendText(roomId, i18n.t(["general", "showalike"]));

    await showProfile(client, roomId, profileInfo);

    await client.sendText(roomId, i18n.t(["general", "mxid"], { mxid: profileInfo.mx_id }));
};

const showNewLikes = async (client, roomId) => {
    let likes = (await getAllLikesForUser(roomId));
    for (let liked of likes) {
        if (await checkForMutualLike(liked.sender, roomId)) {
            await showProfileToUser(client, roomId, liked.sender);
            await markLikeAsRead(liked.sender, roomId);
        }
    }
};

const wait_start = async (client, roomId, current_action, answer, update) => {
    let a = answer.split(" ");
    if (a[0] !== "!start") return;
    if (a[1] !== "ru" && a[1] !== "en") return;
    await setUserLanguage(roomId, a[1]);
    i18n.locale = a[1];
    await setUserState(roomId, update ? "menu" : "location");
    await client.sendText(roomId, i18n.t(["setup", "location"]));
}

const loc = async (client, roomId, current_action, answer, update) => {
    let number = parseInt(answer);
    if (!number) {
        let cities = await findCity(answer);
        await client.sendText(roomId, i18n.t(["setup", "choosecity"], {
            number1: cities[0].id,
            name1: cities[0].name,
            country1: cities[0].country,
            lat1: cities[0].lat,
            lng1: cities[0].lng,

            number2: cities[1].id,
            name2: cities[1].name,
            country2: cities[1].country,
            lat2: cities[1].lat,
            lng2: cities[1].lng,

            number3: cities[2].id,
            name3: cities[2].name,
            country3: cities[2].country,
            lat3: cities[2].lat,
            lng3: cities[2].lng,

            number4: cities[3].id,
            name4: cities[3].name,
            country4: cities[3].country,
            lat4: cities[3].lat,
            lng4: cities[3].lng,

            number5: cities[4].id,
            name5: cities[4].name,
            country5: cities[4].country,
            lat5: cities[4].lat,
            lng5: cities[4].lng,
        }));
    } else {
        await processRequest(client, roomId, current_action, number, update ? "menu" : "range");
    }
}

const range = async (client, roomId, current_action, answer, update) => {
    answer = parseInt(answer.split(" ")[0]);
    if (!answer && answer != 0) {
        await client.sendText(roomId, i18n.t(["setup", "range"]));
        return;
    }
    await processRequest(client, roomId, current_action, answer, update ? "menu" : "name");
}

const age = async (client, roomId, current_action, answer, update) => {
    answer = parseInt(answer);
    if (!answer) {
        await client.sendText(roomId, i18n.t(["setup", "age"]));
        return;
    }

    if (answer < 14) {
        await client.sendText(roomId, i18n.t(["errors", "tooyoung"]));
        await client.leaveRoom(roomId);
        await fullEraseUser(roomId);
        return;
    }
    await processRequest(client, roomId, current_action, answer, update ? "menu" : "sex");
}

const sex = async (client, roomId, current_action, answer, update) => {
    answer = answer.toLowerCase().trim();
    if (answer.toLowerCase() != "male" && answer.toLowerCase() != "female") {
        await client.sendText(roomId, i18n.t(["errors", "twosexes"]));
        return;
    }
    await processRequest(client, roomId, current_action, answer[0], update ? "menu" : "interest");
}

const interest = async (client, roomId, current_action, answer, update) => {
    answer = answer.toLowerCase().trim();
    if (answer != "male" && answer != "female" && answer != "both") {
        await client.sendText(roomId, i18n.t(["errors", "didntunderstand"]));
        return;
    }
    await processRequest(client, roomId, current_action, answer[0], update ? "menu" : "description");
}

const pictures = async (client, roomId, current_action, event, update) => {
    const msgtype = event.content.msgtype;
    if (event.content?.msgtype !== 'm.image' && event.content?.msgtype !== 'm.video') {
        await client.sendText(roomId, i18n.t(["setup", "done"]));
        await setUserState(roomId, update ? "menu" : "view_profiles");
        await showRandomProfileToUser(client, roomId);
    } else {
        let pictures_count = parseInt(await getAmountOfUserPictures(roomId));
        if (pictures_count >= maxAmountOfPhotoesPerUser) {
            await client.sendText(roomId, i18n.t(["errors", "toomuch"]));
            await setUserState(roomId, update ? "menu" : "view_profiles");
            await showRandomProfileToUser(client, roomId);
        } else {
            let mxc = await uploadMediaFromEvent(client, event);
            let type = convertMsgType(msgtype);
            await appendUserPictures(roomId, mxc, type);
            let pictures_count = await getAmountOfUserPictures(roomId);
            if (pictures_count < maxAmountOfPhotoesPerUser) {
                await client.sendText(roomId, i18n.t(["setup", "more"], { amount: String(maxAmountOfPhotoesPerUser - pictures_count) }));
            } else {
                await client.sendText(roomId, i18n.t(["setup", "enough"]));
                await client.sendText(roomId, i18n.t(["setup", "done"]));
                await setUserState(roomId, update ? "menu" : "view_profiles");
                await showRandomProfileToUser(client, roomId);
            }
        }
    }
}

export {
    processRequest,
    showRandomProfileToUser,
    showNewLikes,
    showProfileToUser,
    wait_start,
    loc,
    range,
    age,
    sex,
    interest,
    pictures,
    showProfile
};