import { Router } from 'express';
import axios from 'axios';
import { CONSTANTS_BZ, TEXT_CONSTANTS } from '../constants';
import { getToken_P2P_BZ } from '../utilities';
import { Ticker, PayType, OrderStatus, User } from '../models_nosql';
import {
	getMerchantOrders,
	getBalance,
	getUserPayMethods,
	getMerchantAdvs,
	getArraySortedByProp,
	getArrayFilteredByProp,
	getOrderDetails,
	getTickerPriceUSDT,
	checkOrderInDB,
	insertOrderToDB,
	getP2POrders,
	getSpotOrders,
	getP2POrdersNomalized,
	getMerchantAdvsNomalized,
	getMerchantOrdersNomalized,
	getSpotOrdersNomalized,
	getBalancesNormalized,
	getPayMethodProps,
	getPayMethodPropsReverse,
	getPaySubAccount,
	getSingleUserProperty,
	consoleProcessed,
	getMerchantOrdersByAPI_BZ,
	getOrderDetailsNomalized,
} from '../common';
const {
	SHORT_NAME,
	GET_SPOT_BALANCE,
	GET_P2P_BALANCE,
	GET_FUT_BALANCE,
	GET_EARN_BALANCE,
	TRANSFER_ASSET_FROM_P2P,
	TRANSFER_ASSET_FROM_SPOT,
	GET_P2P_ORDERS,
	GET_MERCHANT_ORDERS_BY_API,
	GET_MERCHANT_ORDERS,
	GET_MERCHANT_ORDER_DETAILS,
	GET_MERCHANT_ORDER_DETAILS_BY_API,
	GET_MERCHANT_ADVS,
	CHANGE_STATUS_ADVS,
	GET_ADV_DETAIL,
	UPDATE_DETAILS_ADV,
	GET_HISTORY_SPOT_ORDERS,
	GET_ACTIVE_SPOT_ORDERS,
	GET_MERCHANT_ADV_PAYMENTS,
	GET_MERCHANT_DETAILS,
} = CONSTANTS_BZ;

export const ordersRouter_BZ = Router();

// получение балансов
ordersRouter_BZ.post('/get-balances', async (req, res) => {
	const { userId, exchange, shortName } = req.body;
	const user = await User.findOne({ _id: userId });
	const requestHeaderBZ = getSingleUserProperty(
		'requestHeader',
		exchange,
		user.properties
	);
	const reqConfig = {
		withCredentials: true,
		method: GET_SPOT_BALANCE.method,
		url: GET_SPOT_BALANCE.url,
		data: null,
		headers: {
			Accept: '*/*',
			'Access-Control-Allow-Origin': '*',
			// 'accept-encoding':'gzip, deflate, br',
			// 'user-agent': req.body.requestHeader.userAgent,
			// cookie: req.body.requestHeader.cookie,
			'user-agent': requestHeaderBZ.userAgent,
			cookie: requestHeaderBZ.cookie,
		},
	};

	// получение spot-, p2p- балансов
	const allBalance = await getBalance(reqConfig, shortName);

	return res.status(200).json({
		success: allBalance.length === 0 ? false : true,
		balances: {
			spotBalance: getBalancesNormalized(allBalance, `${shortName}_spot`),
			p2pBalance: getBalancesNormalized(allBalance, `${shortName}_otc`),
			futBalance: [],
			earnBalance: [],
			lockedData: null,
		},
		message:
			allBalance.length === 0
				? `${shortName}: ${TEXT_CONSTANTS.BALANCE_ER}`
				: `${shortName}: ${TEXT_CONSTANTS.BALANCE_OK}`,
	});
});

// получение массива объявлений
ordersRouter_BZ.post('/merchant-advs', async (req, res) => {
	const { userId, shortName, exchangeId, objParams } = req.body;
	const user = await User.findOne({ _id: userId });
	const requestHeaderBZ = getSingleUserProperty(
		'requestHeader',
		exchangeId,
		user.properties
	);

	const params = {
		userId,
		prefix: shortName,
		config: {
			withCredentials: true,
			method: GET_MERCHANT_ADVS.method,
			url: `${GET_MERCHANT_ADVS.url}?lang=en`,
			data: {},
			headers: {
				'access-control-allow-credentials': true,
				'Access-Control-Allow-Origin': '*',
				'content-type': 'application/json;charset=UTF-8',
				cookie: requestHeaderBZ.cookie,
				'user-agent': requestHeaderBZ.userAgent,
			},
		},
	};

	const arrData = await getMerchantAdvs(params);
	const arrPayTypes = await PayType.find();

	return res.status(200).json({
		success: arrData.length !== 0 ? true : false,
		data: {
			// merchantAdvs: [],
			merchantAdvs:
				arrData.length !== 0
					? getMerchantAdvsNomalized(
							arrData,
							{
								userId,
								exchangeId,
								prefix: shortName,
							},
							arrPayTypes
					  )
					: [],
			userPayMethods: [],
		},
		message:
			arrData.length !== 0
				? `${shortName}: ${TEXT_CONSTANTS.USER_ADVS_OK}`
				: `${shortName}: ${TEXT_CONSTANTS.USER_ADVS_ER}`,
	});
});

// изменение статуса объявления (-ий) мерчанта
ordersRouter_BZ.post('/adv-status', async (req, res) => {
	res.status(400).json({
		error,
		message: `${SHORT_NAME}: ${TEXT_CONSTANTS.ADV_STATUS_ER}`,
	});
});

// получение редактируемого объявления мерчанта
ordersRouter_BZ.post('/adv-edit', async (req, res) => {
	res.status(400).json({
		error,
		message: `${SHORT_NAME}: ${TEXT_CONSTANTS.ADV_EDIT_ER}`,
	});
});

// обновление редактируемого объявления
ordersRouter_BZ.post('/adv-update', async (req, res) => {
	res.status(400).json({
		message: `${SHORT_NAME}: ${TEXT_CONSTANTS.ADV_UPDATE_ER}`,
	});
});

// получение массива p2p-ордеров стакана
ordersRouter_BZ.post('/p2p', async (req, res) => {
	const { userId, exchangeId, shortName, objParams } = req.body;
	const {
		asset,
		fiat,
		arrPayments,
		sideType,
		page,
		rows,
		amount,
	} = objParams;

	const arrPayTypes = await PayType.find();
	const tradeType = sideType === 'BUY' ? 'purchase' : 'selling';
	const paymentIdx =
		arrPayments.length === 0
			? ['']
			: arrPayments.map((item, index) => {
					return getPayMethodPropsReverse(
						exchangeId,
						'payId', // payId or payName
						item, // internalPayMethod
						arrPayTypes
					);
			  });
	const user = await User.findOne({ _id: userId });
	const requestHeaderBZ = getSingleUserProperty(
		'requestHeader',
		exchangeId,
		user.properties
	);

	const params = {
		userId,
		prefix: shortName,
		config: {
			withCredentials: true,
			method: GET_P2P_ORDERS.method,
			url: ``,
			data: null,
			headers: {
				'access-control-allow-credentials': true,
				'Access-Control-Allow-Origin': '*',
				'content-type': 'application/json;charset=UTF-8',
				cookie: requestHeaderBZ.cookie,
				'user-agent': requestHeaderBZ.userAgent,
			},
		},
	};

	let arrData = [];
	for (let i = 0; i < paymentIdx.length; i++) {
		params.config.url = `${GET_P2P_ORDERS.url}?skip=0&limit=${rows}&type=${tradeType}&currency=${fiat}&cryptocurrency=${asset}&isOwnerVerificated=false&isOwnerTrusted=false&isOwnerActive=false&paymethod=${paymentIdx[i]}&amount=${amount}&amountType=currency&lang=en`;
		const result = await getP2POrders(params);
		// console.log(params.config.url);
		arrData = arrData.concat(result);
	}

	return res.status(200).json({
		success: arrData.length !== 0 ? true : false,
		data: {
			// p2pOrders: [],
			p2pOrders:
				arrData.length !== 0
					? getP2POrdersNomalized(
							getArraySortedByProp(shortName, arrData, tradeType),
							{
								userId,
								exchangeId,
								prefix: shortName,
							},
							arrPayTypes
					  )
					: [],
			tickers: await Ticker.find(),
		},
		message:
			arrData.length !== 0
				? `${shortName}: ${arrData.length} ${TEXT_CONSTANTS.P2P_ORDERS_OK}`
				: `${shortName}: ${TEXT_CONSTANTS.P2P_ORDERS_ER}`,
	});
});

// получение массива текущих merchant-ордеров
ordersRouter_BZ.post('/merchant-orders', async (req, res) => {
	const { userId, exchangeId, shortName } = req.body;

	const user = await User.findOne({ _id: userId });
	const requestHeaderBZ = getSingleUserProperty(
		'requestHeader',
		exchangeId,
		user.properties
	);

	const params = {
		userId,
		prefix: shortName,
		config: {
			withCredentials: true,
			method: GET_MERCHANT_ORDERS.method,
			url: `${GET_MERCHANT_ORDERS.url}?limit=15&skip=0`,
			data: null,
			headers: {
				Accept: '*/*',
				'Access-Control-Allow-Origin': '*',
				'user-agent': requestHeaderBZ.userAgent,
				cookie: requestHeaderBZ.cookie,
			},
		},
	};

	const paramsAPI = {
		userId,
		prefix: shortName,
		config: {
			withCredentials: true,
			method: GET_MERCHANT_ORDERS_BY_API.method,
			url: `${GET_MERCHANT_ORDERS_BY_API.url}?limit=15&skip=0`,
			data: null,
			headers: {
				Authorization: `Bearer ${await getToken_P2P_BZ(userId)}`,
				// Authorization: `Bearer ${requestHeaderBZ.token}`,
			},
		},
	};

	// const arrData = await getMerchantOrders(params);
	const arrData = await getMerchantOrdersByAPI_BZ(paramsAPI);

	const arrPayTypes = await PayType.find();
	const arrOrderStatus = await OrderStatus.find();

	return res.status(200).json({
		success: arrData.length !== 0 ? true : false,
		// data: [],
		data:
			arrData.length !== 0
				? getMerchantOrdersNomalized(
						arrData,
						{
							userId,
							exchangeId,
							prefix: shortName, // 'MG'
						},
						arrPayTypes,
						arrOrderStatus
				  )
				: [],
		message:
			arrData.length !== 0
				? `${shortName}: ${arrData.length} ${TEXT_CONSTANTS.USER_ORDERS_OK}`
				: `${shortName}: ${TEXT_CONSTANTS.USER_ORDERS_ER}`,
	});
});

// получение сведений об мерчанте и его объявлениях по id
ordersRouter_BZ.get('/merchant-details/:id', async (req, res) => {
	const merchantId = req.params.id;
	const axiosRequestConfig = {
		method: GET_MERCHANT_DETAILS.method,
		url: `${GET_MERCHANT_DETAILS.url}?userNo=${merchantId}`,
		data: null,
		headers: null,
	};
	await axios(axiosRequestConfig)
		.then((response) => {
			// console.log(response.data)
			return res.status(200).json({
				success: true,
				data: response.data.data,
				message: 'Merchant details were successful loaded',
			});
		})
		.catch((error) => {
			res.status(400).json({
				error,
				message: 'Merchant details were not loaded',
			});
		});
});

// сохранение данных об merchant-ордере в БД по id
ordersRouter_BZ.post('/save-user-orders', async (req, res) => {
	const { userId, orders, typeOrder, shortName, exchangeId } = req.body;
	const user = await User.findOne({ _id: userId });
	const arrTickers = await Ticker.find(); // тикеры и цены из БД
	const arrPayTypes = await PayType.find(); // типы оплаты из БД
	let countOrder = 0;

	const requestHeaderBZ = getSingleUserProperty(
		'requestHeader',
		exchangeId,
		user.properties
	);

	// проверка наличия ордера в БД
	for (let i = 0; i < orders.length; i++) {
		if (orders[i] !== null) {
			const result = await checkOrderInDB(
				userId,
				typeOrder,
				orders[i],
				shortName
			);

			// Если ордера нет в БД
			if (result.isUnique) {
				const config = {
					// method: GET_MERCHANT_ORDER_DETAILS.method,
					method: GET_MERCHANT_ORDER_DETAILS_BY_API.method,
					// url: `${GET_MERCHANT_ORDER_DETAILS.url}${orders[i]}`,
					url: `${GET_MERCHANT_ORDER_DETAILS_BY_API.url}${orders[i]}`,
					data: null,
					headers: {
						// 'access-control-allow-credentials': true,
						// 'Access-Control-Allow-Origin': '*',
						// 'content-type': 'application/json;charset=UTF-8',
						// cookie: requestHeaderBZ.cookie,
						// 'user-agent': requestHeaderBZ.userAgent,
						Authorization: `Bearer ${await getToken_P2P_BZ(userId)}`,
					},
				};

				// получение данных об ордере с биржи
				const orderDetails = await getOrderDetails(
					config,
					shortName, // BZ
					typeOrder
				);

				// Проверка завершенности ордера
				const checkCompletedStatusBZ = (arrHistory) => {
					let status = false;
					for (let i = 0; i < arrHistory.length; i++) {
						if (arrHistory[i].status === 'confirm_payment') status = true;
					}
					return status;
				};

				const params = {
					userId,
					shortName,
					exchangeId,
					arrTickers,
					arrPayTypes,
					orderDetails,
				};

				// если orderDetails не пустой объект - подготовка к сохранению БД
				if (Object.keys(orderDetails).length !== 0) {
					const isCompleted = checkCompletedStatusBZ(orderDetails.history);

					// если статус ордера "Completed" вставляем в БД
					const newOrder = isCompleted
						? getOrderDetailsNomalized(params)
						: {};
					// если newOrder не пустой объект - сохраняем в БД
					if (Object.keys(newOrder).length !== 0) {
						await insertOrderToDB(typeOrder, newOrder);
						// console.log(`${countOrder} | Number: ${newOrder.orderId} | priceAssetUSDT: ${newOrder.priceAssetUSDT}`);
						++countOrder;
					}
				}
			}
		}
	}

	// log print
	consoleProcessed(userId, shortName, orders, countOrder, typeOrder);

	return res.status(200).json({
		success: true,
		message: `${shortName}: ${countOrder} inserted`,
	});
});

// получение массива активных spot-ордеров
ordersRouter_BZ.post('/spot-orders-active', async (req, res) => {
	// const typeOrder = req.body.typeOrder;
	// const shortName = req.body.shortName;
	const { userId, exchange, exchangeId } = req.body;
	const arrTickers = await Ticker.find();
	let status = 200;

	const user = await User.findOne({ _id: userId });
	const requestHeader = getSingleUserProperty(
		'requestHeader',
		exchange,
		user.properties
	);

	// проверям существуют ли куки на этом сервисе
	if (requestHeader.userAgent === '') {
		return res.status(status).json({
			success: true,
			message: `${SHORT_NAME}: requestHeader is empty`,
			spotOrders: [],
			tickers: await Ticker.find(),
		});
	}

	const headers = {
		'access-control-allow-credentials': true,
		'Access-Control-Allow-Origin': '*',
		'content-type': 'application/json;charset=UTF-8',
		cookie: requestHeader.cookie,
		'user-agent': requestHeader.userAgent,
	};

	const params = {
		userId,
		prefix: SHORT_NAME,
		config: {
			withCredentials: true,
			method: GET_ACTIVE_SPOT_ORDERS.method,
			url: `${GET_ACTIVE_SPOT_ORDERS.url}?page=1&limit=25&state`,
			data: null,
			headers,
		},
	};

	const arrActiveSpots = await getSpotOrders(params);

	return res.status(status).json({
		success: arrActiveSpots && arrActiveSpots.length !== 0 ? true : false,
		message:
			arrActiveSpots && arrActiveSpots.length !== 0
				? `${SHORT_NAME}: ${arrActiveSpots.length} ${TEXT_CONSTANTS.SPOT_ORDERS_OK}`
				: `${SHORT_NAME}: ${TEXT_CONSTANTS.SPOT_ORDERS_ER}`,
		spotOrders:
			arrActiveSpots && arrActiveSpots.length !== 0
				? getSpotOrdersNomalized(
						arrActiveSpots,
						{
							userId,
							exchangeId,
							shortName: SHORT_NAME,
							flag: 'active_BZ',
						},
						arrTickers
				  )
				: [],
		tickers: await Ticker.find(),
	});
});

// сохранение spot-ордеров в БД
ordersRouter_BZ.post('/spot-orders-history', async (req, res) => {
	let message;
	let success = true;
	let status = 200;
	let countOrder = 0;
	const {
		userId,
		exchange,
		exchangeId,
		shortName,
		typeOrder,
		params,
	} = req.body;

	const user = await User.findOne({ _id: userId });
	const requestHeader = getSingleUserProperty(
		'requestHeader',
		exchange,
		user.properties
	);

	const objParams = {
		userId,
		prefix: shortName,
		config: {
			withCredentials: true,
			method: GET_HISTORY_SPOT_ORDERS.method,
			url: `${GET_HISTORY_SPOT_ORDERS.url}?page=1&limit=${params.rows}&state=done`,
			data: null,
			headers: {
				'access-control-allow-credentials': true,
				'Access-Control-Allow-Origin': '*',
				'content-type': 'application/json;charset=UTF-8',
				cookie: requestHeader.cookie,
				'user-agent': requestHeader.userAgent,
			},
		},
	};
	const arrTickers = await Ticker.find();
	const spotArray = await getSpotOrders(objParams);

	const spotOrders = getSpotOrdersNomalized(
		spotArray,
		{
			userId,
			shortName: shortName,
			exchangeId,
			flag: 'history_BZ',
		},
		arrTickers
	);

	if (spotOrders.length !== 0) {
		// проверка наличия ордера в БД
		for (let i = 0; i < spotOrders.length; i++) {
			const result = await checkOrderInDB(
				spotOrders[i].userId,
				typeOrder,
				spotOrders[i].orderId,
				spotOrders[i].exchange
			);

			// Если ордера нет в БД вставляем
			if (result.isUnique) {
				// если newSpotOrder не пустой объект - сохраняем в БД
				if (Object.keys(spotOrders[i]).length !== 0) {
					await insertOrderToDB('SPOT', spotOrders[i]);
					// console.log(
					// 	`${countOrder} | tradeIdStr: ${spotOrders[i].tradeIdStr} inserted`
					// );
					++countOrder;
				}
			}
			// else console.log(`Order ${spotOrders[i].orderId} is not Unique`);
		}
		if (countOrder === 0) {
			success = false;
			message = `${shortName}: ${countOrder} | ${TEXT_CONSTANTS.SPOT_ORDERS_DB_NO}`;
		} else {
			success = true;
			message = `${shortName}: ${countOrder} | ${TEXT_CONSTANTS.SPOT_ORDERS_DB_OK}`;
		}
	} else {
		success = false;
		message = `${shortName}: ${TEXT_CONSTANTS.SPOT_ORDERS_ER}`;
	}

	// log print
	consoleProcessed(userId, shortName, spotOrders, countOrder, typeOrder);

	return res.status(status).json({
		success,
		message,
	});
});
