import axios from 'axios';
import { Cookies } from 'react-cookie';
import Router from 'next/router';
import moment from 'moment';
import { nSQL } from "@nano-sql/core";

import * as actionTypes from '../constants/actionTypes';
import * as currentState from '../reducers/initialState';
import { eachSeries } from 'async';

if(process.browser)
{
	FormData.prototype.appendObject = function(obj, namespace) 
	{
		let keyName;
		for (var key in obj) 
		{
			if (obj.hasOwnProperty(key)) 
			{
				keyName = [namespace, '[', key, ']'].join('');
				this.append(keyName, obj[key]);
			}
		}
	};	
}

export const getContract = ({ dispatch, number, }) => 
{
	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract`, {
			number: number
		}, 
		{
			withCredentials: true, 
		})
		.then((response) => 
		{
			console.log("response.data");
			console.log(response.data);

			dispatch({ 
				type: actionTypes.CONTRACT_PAYMENTS, 
				data: { 
					payments: response.data.payments, 
					avans: response.data.avans, 
					debt: response.data.paymentDebt, 
					penalty: response.data.penyDebt 
				} 
			});

			resolve();
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractInfo = ({ dispatch, number, }) => 
{
	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/info`, {
			number: number
		}, 
		{
			withCredentials: true, 
		})
		.then((response) => 
		{
			const info = { date: response.data.dl_date, car: response.data.car, status: response.data.status };
			dispatch({ type: actionTypes.CONTRACT_INFO, data: info });

			const contract = {};
			contract[`${ number }`] = info;

			dispatch({ type: actionTypes.CONTRACTS_INFO, data: contract });

			resolve(info);
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractInsurance = ({ dispatch, number, }) => 
{
	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/insurance`, {
			number: number
		}, 
		{
			withCredentials: true, 
		})
		.then((response) => 
		{
			dispatch({ type: actionTypes.CONTRACT_INSURANCE, data: { insurance: response.data } });

			resolve();
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractHelpCard = ({ dispatch, number, }) => 
{
	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/helpcard`, {
			number: number
		}, 
		{
			withCredentials: true, 
		})
		.then((response) => 
		{
			dispatch({ type: actionTypes.CONTRACT_HELPCARD, data: { helpcard: response.data } });

			resolve();
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractRegistration = ({ dispatch, number, }) => 
{
	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/registration`, {
			number: number
		}, 
		{
			withCredentials: true, 
		})
		.then((response) => 
		{
			dispatch({ type: actionTypes.CONTRACT_REGISTRATION, data: { registration: response.data } });

			resolve();
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractTelematic = ({ dispatch, number, }) => 
{
	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/telematic`, {
			number: number
		}, 
		{
			withCredentials: true, 
		})
		.then((response) => 
		{
			dispatch({ type: actionTypes.CONTRACT_TELEMATIC, data: { telematic: response.data } });

			resolve();
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractAgreement = ({ dispatch, number, }) => 
{
	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/agreement`, {
			number: number
		}, 
		{
			withCredentials: true, 
		})
		.then((response) => 
		{
			const unsigned = {
				count: 0, 
				documents: {
					contracts: [], 
					redemptions: [], 
					agreements: [], 
					assignments: [], 
				}, 
			};

			const signed = {
				count: 0, 
				documents: {
					contracts: [], 
					redemptions: [], 
					agreements: [], 
					assignments: [], 
				}, 
			};

			console.log("ACTION", "getContractAgreement", "-".repeat(30));
			console.log("ACTION", "getContractAgreement", "response.data", response.data);
			console.log("ACTION", "getContractAgreement", "-".repeat(30));

			for(let i in response.data)
			{
				for(let d in response.data[i].documents)
				{
					if(response.data[i].documents[d].signed)
					{
						signed.documents[response.data[i].type].push( response.data[i].documents[d] );
						signed.count++;
					}
					else
					{
						unsigned.documents[response.data[i].type].push( response.data[i].documents[d] );
						unsigned.count++;
					}
				}
			}

			console.log("ACTION", "getContractAgreement", "-".repeat(30));
			console.log("ACTION", "getContractAgreement", "unsigned", unsigned);
			console.log("ACTION", "getContractAgreement", "signed", signed);
			console.log("ACTION", "getContractAgreement", "-".repeat(30));

			dispatch({ type: actionTypes.CONTRACT_AGREEMENT, data: { agreement: { unsigned, signed } } });

			resolve();
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractDocuments = ({ dispatch, number, }) => 
{
	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/documents`, {
			number: number
		}, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{

			console.log("getDocuments", "response.data", response.data);

			const documents = { upd: [], upd_avans: [], fines: [] };

			await Promise.all([
			new Promise((pr) => 
			{
				let query = nSQL(response.data.upd).query("select");
				query = query.orderBy({ date: "desc" });

				query.exec().then((rows) => 
				{
					documents.upd = rows;
					pr();
				});	
			}), new Promise((pr) => 
			{
				let query = nSQL(response.data.upd_avans).query("select");
				query = query.orderBy({ date: "desc" });

				query.exec().then((rows) => 
				{
					documents.upd_avans = rows;
					pr();
				});	
			}), new Promise((pr) => 
			{
				let query = nSQL(response.data.billfines).query("select");
				query = query.orderBy({ date: "desc" });

				query.exec().then((rows) => 
				{
					documents.billfines = rows;
					pr();
				});	
			})])
			.then(() => 
			{
				console.log("documents");
				console.log(documents);
				dispatch({ type: actionTypes.CONTRACT_DOCUMENTS, data: { documents: documents } });
				resolve();	
			});
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractFines = ({ dispatch, number, }) => 
{
	console.log("ACTION", "getContractFines");

	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/fines`, {
			number: number
		}, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{

			console.log("ACTION", "getContractFines", "response.data", response.data);

			let fines = [];

			let query = nSQL(response.data.fines).query("select");
			query = query.orderBy({ date: "desc" });
			query.exec().then((rows) => 
			{
				fines = rows;

				console.log("fines");
				console.log(fines);
				dispatch({ type: actionTypes.CONTRACT_FINES, data: { fines: fines } });
				resolve();	
			});
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractRules = ({ dispatch, date, }) => 
{
	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/rules`, {
			date: date
		}, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{
			console.log("getContractRules", "response.data", response.data);
			dispatch({ type: actionTypes.CONTRACT_RULES, data: { rules: response.data.rules } });

			resolve();
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractMaterials = ({ dispatch, }) => 
{
	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/materials`, {
		}, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{
			console.log("getContractMaterials", "response.data", response.data);
			dispatch({ type: actionTypes.CONTRACT_MATERIALS, data: { materials: response.data.materials } });

			resolve();
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractPenalties = ({ number, date }) => 
{
	console.log("ACTION", "getContractPenalties", { number, date });

	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/penalties`, {
			number, date
		}, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{
			console.log("getContractPenalties", "response.data", response.data);
			resolve(response.data);
		})
		.catch((error) => 
		{
			console.error(error);
			reject();
		});
	});
}

export const getContractGraphicChange = ({ dispatch, number }) => 
{
	return new Promise(async (resolve, reject) => 
	{
		await Promise.all([
			getContractGraphicChangeSignatories({ dispatch, number }), 
			getContractGraphicChangeVariants({ dispatch, number, variants: {
				change_payment_date: false, 
				insurance_change: false, 
				last_payment_change: false, 
				date_offset_change: false, 
				contract_term_change: false, 
				sum_pay_change: false, 
				early_redemption_change: false, 
			} }), 
			getContractGraphicChangeCalculationsList({ dispatch, number }), 
		])
		.then(() => 
		{
			resolve();
		});	
	});
}

export const getContractGraphicChangeSignatories = ({ dispatch, number }) => 
{
	console.log("ACTION", "getContractGraphicChangeSignatories", { number });

	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/signatories`, { number }, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{
			console.log("ACTION", "getContractGraphicChangeSignatories", "response.data", response.data);

			dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { signatories: response.data.signatories } });
			resolve();
		})
		.catch((error) => 
		{
			console.error("ACTION", "getContractGraphicChangeSignatories", "error");
			console.error(error.response.data);

			reject(error.response.data);
		});
	});
}

export const getContractGraphicChangeVariants = ({ dispatch, number, variants = {} }) => 
{
	console.log("ACTION", "getContractGraphicChangeVariants", { ...{ number }, ...{ variants: variants } });

	return new Promise((resolve, reject) => 
	{
		console.log("{ ...{ number }, ...variants }", { ...{ number }, ...{ variants: variants } });

		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/variants`, { ...{ number }, ...{ variants: variants } }, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{
			console.log("ACTION", "getContractGraphicChangeVariants", "response.data", response.data);

			dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { variants: response.data } });
			resolve();
		})
		.catch((error) => 
		{
			console.error("ACTION", "getContractGraphicChangeVariants", "error");
			console.error(error.response.data);

			reject(error.response.data);
		});
	});
}

export const getContractGraphicChangeCalculationsList = ({ dispatch, number }) => 
{
	console.log("ACTION", "getContractGraphicChangeCalculationsList", { number });

	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/calculations`, { number }, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{
			console.log("ACTION", "getContractGraphicChangeCalculationsList", "response.data", response.data);

			dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { calculations: response.data.pre_calculations } });
			resolve();
		})
		.catch((error) => 
		{
			console.error("ACTION", "getContractGraphicChangeCalculationsList", "error");
			console.error(error.response.data);

			reject(error.response.data);
		});
	});
}

export const getContractGraphicChangeOptions = ({ dispatch, number, variants }) => 
{
	console.log("ACTION", "getContractGraphicChangeOptions", { ...{ number }, ...variants });

	return new Promise((resolve, reject) => 
	{
		console.log("{ ...{ number }, ...variants }", { ...{ number }, ...variants });

		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/options`, { ...{ number }, ...{ variants: variants } }, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{
			console.log("ACTION", "getContractGraphicChangeOptions", "response.data", response.data);

			dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { options: response.data.planpayments[0] } });
			resolve();
		})
		.catch((error) => 
		{
			console.error("ACTION", "getContractGraphicChangeOptions", "error");
			console.error(error.response.data);

			reject(error.response.data);
		});
	});
}

export const getContractGraphicChangeCalculate = (calculation) => 
{
	console.log("ACTION", "getContractGraphicChangeCalculate", calculation);

	return new Promise((resolve, reject) => 
	{

		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/graphic/calculate`, calculation, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{
			console.log("ACTION", "getContractGraphicChangeCalculate", "response.data", response.data);
			resolve(response.data);
		})
		.catch((error) => 
		{
			console.error("ACTION", "getContractGraphicChangeCalculate", "error");
			console.error(error.response.data);

			reject(error.response.data);
		});
	});
}

export const getContractGraphicChangeGetCurrent = ({ dispatch, number }) => 
{
	console.log("ACTION", "getContractGraphicChangeGetCurrent", { number });

	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/graphic/current`, { number }, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{
			console.log("ACTION", "getContractGraphicChangeGetCurrent", "response.data", response.data);

			dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { current: { payments: response.data.planpayments, total: response.data.sum_total } } });
			resolve();
		})
		.catch((error) => 
		{
			console.error("ACTION", "getContractGraphicChangeGetCurrent", "error");
			console.error(error.response.data);

			reject(error.response.data);
		});
	});
}

export const getContractGraphicChangeGetCalculated = ({ dispatch, calculation }) => 
{
	console.log("ACTION", "getContractGraphicChangeGetCalculated", { calculation });

	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/graphic/calculation`, { calculation }, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{
			console.log("ACTION", "getContractGraphicChangeGetCalculated", "response.data", response.data);

			dispatch({ type: actionTypes.CONTRACT_CHANGE, data: { calculated: { payments: response.data.planpayments, total: response.data.sum_total } } });
			resolve();
		})
		.catch((error) => 
		{
			console.error("ACTION", "getContractGraphicChangeGetCalculated", "error");
			console.error(error.response.data);

			reject(error.response.data);
		});
	});
}

export const signContractGraphicChange = (params) => 
{
	console.log("ACTION", "signContractGraphicChange", params);

	return new Promise((resolve, reject) => 
	{
		axios.post(`${ process.env.NEXT_PUBLIC_SELF_API_HOST }/api/contract/change/graphic/sign`, params, 
		{
			withCredentials: true, 
		})
		.then(async (response) => 
		{
			console.log("ACTION", "signContractGraphicChange", "response.data", response.data);
			resolve(response.data.comment);
		})
		.catch((error) => 
		{
			console.error("ACTION", "signContractGraphicChange", "error");
			console.error(error.response.data);

			reject(error.response.data);
		});
	});
}