import { User, Exchange } from '../models_nosql';
import { TG_BOT, CURRENCY_SYMBOLS as symbols } from '../constants';
import { bot, getToken_P2P_BZ } from '../utilities';
import {
	getTimestamps,
	updateAuthToken_BZ_GX,
	getSingleUserProperty,
	getMerchantOrdersByAPI_BZ,
	getMerchantOrders,
	getObjExchangeById,
	getObjectRequestParams,
	getArrayItemsCustomed,
	startHandlerAllOtcOrders,
} from '../common';

if (TG_BOT) {
	// Хранилище таймеров
	const arrTimers = [];

	// Обработчик хранилища таймеров
	const handlerArrIntervals = async (id, nameFlag, params) => {
		// поиск юзера по id_tgbot
		const user = await User.findOne({ id_tgbot: id });
		if (user) {
			const properties = user.properties;
			if (nameFlag === 'removeId_tgbot') {
				if (arrTimers.length !== 0) {
					let count = 0;
					for (let i = 0; i < arrTimers.length; i++) {
						if (arrTimers[i].idChat === id) {
							count++;
							clearInterval(arrTimers[i].idInterval);
							// удаление таймера из хранилища
							arrTimers.splice(i, 1);
							// удаление таймера из БД
							user.id_tgbot = '';
							// сохраняем изменения
							user.save().then(() => {
								bot.sendMessage(
									id,
									`${user.login}\nNotifications disabled`
								);
								console.log(`${user.login} | id_tgbot removed`);
							});
						}
					}
					// если arrTimers не пустой, но совпадений нет
					if (count === 0) {
						bot.sendMessage(id, `Bot not started. Click /start`);
						console.log('User id_tgbot not found');
					}
				} else {
					bot.sendMessage(id, `Bot not started. Click /start`);
					console.log(`arrTimers is empty`);
				}
			} else if (nameFlag === 'get_statuses') {
				let message = '';
				let totalUnpaid = 0;
				let totalPaid = 0;
				let totalAppeal = 0;
				for (let j = 0; j < properties.length; j++) {
					const shortName = modifyResponseText(
						'getShortName',
						properties[j].exchange,
						params
					);
					const onOff = properties[j].updateOrders ? 'on' : 'off';
					const { orderStatuses } = properties[j];
					const { unpaid, paid, appeal, reject } = orderStatuses;
					totalUnpaid += unpaid;
					totalPaid += paid;
					totalAppeal += appeal;
					const statuses =
						onOff === 'on'
							? `U: ${getValue(unpaid)} | P: ${getValue(
									paid
							  )} | A: ${getValue(appeal)}`
							: null;
					// пропуск, если биржа не подключена
					shortName !== ''
						? (message += `${onOff} | ${statuses} | ${shortName}\n`)
						: null;
				}
				const line = '=======================';
				const total = `--- | U: ${totalUnpaid} | P: ${totalPaid} | A: ${totalAppeal} | ALL`;
				bot.sendMessage(
					id,
					`${user.login}\n${total}\n${line}\n${message}`
				);
			} else {
				// nameFlag === "Pexpay"
				let onOff;
				for (let j = 0; j < properties.length; j++) {
					if (properties[j].exchange === nameFlag) {
						properties[j].updateOrders = !properties[j].updateOrders;
						onOff = properties[j].updateOrders ? 'started' : 'stoped';
					}
				}
				user.properties = properties;
				// сохраняем изменения
				user.save().then(() => {
					bot.sendMessage(id, `${user.login}\n${nameFlag} ${onOff}`);
					console.log(`${user.login} | updateOrders changed`);
				});
			}
		} else {
			bot.sendMessage(id, `Bot not started. Click /start`);
			console.log('User id_tgbot not found');
		}
	};

	// обработчик print value
	const getValue = (value) => {
		const result = +value > 0 ? value : '-';
		return result;
	};

	// обновление userProperties по exchangeId
	const updateUserProps = (arrProps, arrOrderStatuses) => {
		for (let i = 0; i < arrProps.length; i++) {
			for (let j = 0; j < arrOrderStatuses.length; j++) {
				if (arrProps[i].exchangeId === arrOrderStatuses[j].exchangeId) {
					arrProps[i].orderStatuses.unpaid = arrOrderStatuses[j].unpaid;
					arrProps[i].orderStatuses.paid = arrOrderStatuses[j].paid;
					arrProps[i].orderStatuses.appeal = arrOrderStatuses[j].appeal;
				}
			}
		}
		return arrProps;
	};

	// преобразование Short <=> Full
	const modifyResponseText = (flag, text, params) => {
		let result = '';
		if (flag === 'getFullName') {
			for (let k = 0; k < params.short.length; k++) {
				if (params.short[k].toLocaleLowerCase() === text)
					result = params.full[k];
			}
		} else {
			// flag === "getShortName"
			for (let k = 0; k < params.full.length; k++) {
				if (params.full[k] === text) result = params.short[k];
			}
		}
		return result;
	};

	// получение количества неудачных попыток получения ордеров
	const handlerSummRejects = (arr, exchangeId, flag) => {
		let countRejects = 0;
		for (let i = 0; i < arr.length; i++) {
			if (arr[i].exchangeId === exchangeId) {
				if (flag === 'read') {
					countRejects = arr[i].rejects;
				} else if (flag === 'write0') {
					arr[i] = { ...arr[i], rejects: 0 };
					// countRejects = arr[i].rejects;
				} else if (flag === 'write1') {
					arr[i] = { ...arr[i], rejects: arr[i].rejects + 1 };
					countRejects = arr[i].rejects;
				}
			}
		}
		return countRejects;
	};

	// получение символа по названию фиата
	const getSymbolByFiat = (fiat) => {
		const arr = symbols.filter((symbol) => {
			return symbol.fiat === fiat;
		});

		return arr.length !== 0 ? arr[0]['sym'] : '*';
	};

	// обработчик сообщения пользователя
	bot.on('message', async (msg) => {
		const { id } = msg.chat;
		if (TG_BOT) {
			const arrExchanges = await Exchange.find();

			const filterdExchanges = getArrayItemsCustomed(
				arrExchanges,
				'arrExchanges'
			).filter((item) => {
				return item.status;
			});
			// Хранилище short- names
			const arrShortExchanges = filterdExchanges.map((item) => {
				return item.shortName;
			});
			// Хранилище long- names
			const arrFullExchanges = filterdExchanges.map((item) => {
				return item.name;
			});
			// Хранилище rejects
			const arrSummRejects = filterdExchanges.map((item) => {
				return {
					shortName: item.shortName,
					exchangeId: item.id,
					rejects: 0,
				};
			});

			const txt = msg.text.trim().toLocaleLowerCase();
			const prms = { short: arrShortExchanges, full: arrFullExchanges };
			// console.log(prms);
			if (txt === '/status') {
				handlerArrIntervals(id, 'get_statuses', prms);
			} else if (txt === '/pause') {
				bot.sendMessage(id, 'Enter exchangeName', {
					reply_markup: {
						keyboard: [arrShortExchanges],
						resize_keyboard: true,
						one_time_keyboard: true,
					},
				});
			} else if (txt === '/advs') {
				bot.sendMessage(id, 'Will soon');
			} else if (txt === '/blns') {
				bot.sendMessage(id, 'Will soon');
			} else if (txt === '/tkrs') {
				bot.sendMessage(id, 'Will soon');
			} else if (txt === '/start') {
				bot.sendMessage(id, 'Enter your email login', prms);
			} else if (txt === '/stop') {
				handlerArrIntervals(id, 'removeId_tgbot', prms);
			} else if (
				txt === 'bn' ||
				txt === 'hb' ||
				txt === 'kx' ||
				// txt === 'bz' ||
				txt === 'gx' ||
				txt === 'bt' ||
				txt === 'bp' ||
				// txt === 'px' ||
				txt === 'mg' ||
				txt === 'kc' ||
				txt === 'gt' ||
				txt === 'ax' ||
				txt === 'bg' ||
				txt === 'bx' ||
				// txt === 'cx' ||
				txt === 'tg' ||
				txt === 'xg' ||
				txt === 'cn' ||
				txt === 'bm' ||
				txt === 'cm' ||
				txt === 'xt'
			) {
				const str = modifyResponseText('getFullName', txt, {
					short: arrShortExchanges,
					full: arrFullExchanges,
				});
				handlerArrIntervals(id, str);
			}
			// if( txt !== "/stop" && txt !== "/start" && txt !== "/pause"){
			else {
				const user = await User.findOne({ login: txt });
				// если пользователь по логину нашелся
				if (user) {
					const nickName = getSingleUserProperty(
						'userNickName',
						'Binance',
						user.properties
					);
					if (user.id_tgbot === '') {
						user.id_tgbot = id;
						user
							.save()
							.then(() =>
								console.log(`${user.login} | saved id_tgbot: ${id}`)
							);
					}

					const idInterval = setInterval(async () => {
						const allOrders = await startHandlerAllOtcOrders({
							userId: user._id.toString(),
							isInsertOrders: false,
							typeOrder: 'MERCHANT',
						});
						const m0 = '=============+=============+=============';
						const m1 = '-------------+-------------+-------------';
						const printUserID = `****${user._id.toString().slice(-4)}`;
						console.log(
							`${printUserID} | ${getTimestamps()} | orderStatuses updated!\n${m1}`
						);

						const arrOrderStatuses = [];
						const summRejects = 3;
						let totalUnpaid = 0;
						let totalPaid = 0;
						let totalAppeal = 0;
						let totalReject = 0;

						for (let i = 0; i < allOrders.length; i++) {
							const updateOrders = getSingleUserProperty(
								'updateOrders',
								allOrders[i].exchangeId,
								user.properties
							);
							const countRejects = handlerSummRejects(
								arrSummRejects,
								allOrders[i].exchangeId,
								'read'
							);
							const orders = allOrders[i].orders.slice();
							if (orders.length === 0) {
								// увеличение счетчика Rejects
								handlerSummRejects(
									arrSummRejects,
									allOrders[i].exchangeId,
									'write1'
								);
								if (countRejects > summRejects && updateOrders) {
									const ms0 =
										allOrders[i].shortName === 'BN'
											? 'server time'
											: 'cookies';
									const msg = `${printUserID} | ${allOrders[i].shortName} | Update ${ms0}!`;
									bot.sendMessage(id, `${msg}\n${getTimestamps()}`);
									if (allOrders[i].shortName === 'GX') {
										const requestHeader = getSingleUserProperty(
											'requestHeader',
											'Garantex',
											user.properties
										);
										const userProps = user.properties.slice();
										const userPropsUpdated = await updateAuthToken_BZ_GX(
											'Garantex',
											userProps,
											user._id,
											requestHeader
										);
										user.properties = userPropsUpdated;
									}
								}
							} else {
								// сброс счетчика Rejects
								handlerSummRejects(
									arrSummRejects,
									allOrders[i].exchangeId,
									'write0'
								);
							}
							const unpaidOrders = orders.filter((item) => {
								return (
									item.statusProps.value === 'Unpaid' ||
									item.statusProps.value === 'Created'
								);
							});
							const unpaid = unpaidOrders.length;
							const paid = orders.filter((item) => {
								return item.statusProps.value === 'Paid';
							}).length;
							const appeal = orders.filter((item) => {
								return item.statusProps.value === 'Appealing';
							}).length;
							const completed = orders.filter((item) => {
								return item.statusProps.value === 'Completed';
							}).length;
							const obj = {
								exchangeId: allOrders[i].exchangeId,
								prefix: allOrders[i].shortName,
								unpaid: isNaN(unpaid) ? 0 : unpaid,
								paid: isNaN(paid) ? 0 : paid,
								appeal: isNaN(appeal) ? 0 : appeal,
								completed: isNaN(completed) ? 0 : completed,
								reject: countRejects,
							};
							if (obj.unpaid > 0) {
								for (let i = 0; i < unpaidOrders.length; i++) {
									const {
										orderId,
										price,
										amount,
										volume,
										asset,
										fiat,
										tradeType,
									} = unpaidOrders[i];
									const sym = getSymbolByFiat(fiat);
									const msg = `${
										obj.prefix
									} | ${tradeType.toLowerCase()} | ${asset} | ${sym}${Number(
										amount
									).toFixed(2)} | **${orderId.slice(-4)} | ${Number(
										price
									).toFixed(2)}`;
									// send a message to TG
									bot.sendMessage(id, `${msg}\n${getTimestamps()}`);
								}
							}
							// print a message to console
							console.log(
								`_${obj.prefix} | U: ${getValue(
									obj.unpaid
								)} | P: ${getValue(obj.paid)} | A: ${getValue(
									obj.appeal
								)} | R: ${getValue(obj.reject)} | C: ${obj.completed}`
							);
							// calculating total values
							totalUnpaid += obj.unpaid;
							totalPaid += obj.paid;
							totalAppeal += obj.appeal;
							totalReject += obj.reject;

							// обновляем statuses
							arrOrderStatuses.push(obj);
						}

						const arrUserProps = user.properties.slice();
						// сохраняем unpaid Statuses в БД
						user.properties = updateUserProps(
							arrUserProps,
							arrOrderStatuses
						);

						user
							.save()
							.then(() => {
								const m2 = `ALL | U: ${totalUnpaid} | P: ${totalPaid} | A: ${totalAppeal} | R: ${totalReject} | C: --`;
								console.log(`${m1}\n${m2}\n${m0}`);
							})
							.catch((error) =>
								console.log('Error insert orderStatuses' + '\n' + error)
							);
					}, 90000);

					// сохраняем запись о таймере в хранилище
					arrTimers.push({ idChat: id, idInterval });
					// отправка приветствия от бота в чат
					bot.sendMessage(
						id,
						`Hello, ${nickName}!\nNotifications enabled`
					);
					console.log(`${getTimestamps()} | ${nickName} TG_BOT started`);
				}
				// если пользователь по логину не нашелся
				else {
					bot.sendMessage(
						id,
						`${txt} is invalid login or incorrect comand`
					);
				}
			}
		} else bot.sendMessage(id, 'TG_BOT false');
	});
}
