// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import fs from 'fs';
import axios from 'axios';
import { Cookies } from 'react-cookie';
import cookie from 'cookie';
import moment from 'moment';
import jwt from 'jsonwebtoken';
import FormData from 'form-data';
import Redis from 'ioredis';
import md5 from 'md5';
import { inspect } from 'util';
import multer from 'multer';
import { get as _get, pick as _pick } from 'lodash';
import { eachSeries } from 'async';
import archiver from 'archiver';

import { fileTypeFromBuffer, fileTypeFromFile } from "file-type";
//import { MIMEType } from 'util';

import { cors } from '../../../lib/cors';
import RedisClient from '../../../lib/RedisClient';

const storage = multer.memoryStorage();
const upload = multer({ storage: storage });

const uploads = `${ __dirname }/../../../../../uploads/`;

function checkNullEmpty(value)
{
	if(value === null) { return false; }
	if(value === "") { return false; }

	return true;
}

function createZipFile(zip_filename, files)
{
	return new Promise((resolve) => 
	{
		const output = fs.createWriteStream(`${ uploads }${ zip_filename }`);
		const archive = archiver('zip', {
			zlib: { level: 9 } // Sets the compression level.
		});

		output.on('close', function() 
		{
			console.log('archive on close');
			resolve();
		});

		output.on('end', function() 
		{
			console.log('archive on end');
		});

		archive.on('warning', function(err) 
		{
			if (err.code === 'ENOENT') 
			{
				// log warning
			} else {
				// throw error
				throw err;
			}
		});

		archive.on('error', function(err) 
		{
			throw err;
		});

		archive.pipe(output);

		for(let i in files)
		{
			archive.append(fs.createReadStream(files[i].path), { name: files[i].name });			
		}
		archive.finalize();
	});
}

export default async function handler(req, res) 
{
	console.log("API", "questionnaire", "send");
	await cors(req, res);

	return new Promise((resolve) => 
	{
		if(req.headers.cookie !== undefined)
		{
			const cookies = cookie.parse(req.headers?.cookie ? req.headers?.cookie : "");

			if(cookies.jwt !== undefined && cookies.jwt !== null)
			{
				var client_jwt_decoded = jwt.verify(cookies.jwt, process.env.JWT_SECRET_CLIENT);
				var crm_jwt = jwt.sign({ acc_number: client_jwt_decoded.acc_number }, process.env.JWT_SECRET_CRM, { noTimestamp: true });

				console.log("JWT", cookies.jwt);
				console.log("CRM_JWT", crm_jwt);

				upload.single("file")(req, {}, async (err) => 
				{
					const { file } = req;

					const id = parseInt(req.body.id, 10);
					const digital = req.body.digital == "true" ? true : false;
					console.log("id, digital", { id, digital });

					const path = `${ process.env.CRM_API_HOST }/lk/Questionnaire/PreQuestionnaire/`;

					const filetype = await fileTypeFromBuffer(file.buffer);
					const timemark = moment().format("YYYY_MM_DD_HH_mm_ss");

					const local_filename = digital 
					? `${ client_jwt_decoded.acc_number }_questionnaire_${ timemark }.sig`
					: `${ client_jwt_decoded.acc_number }_signed_questionnaire_${ timemark }.${ filetype.ext }`;

					const key = md5(`questionnaire_${ client_jwt_decoded.acc_number }`);
					const questionnaire = await RedisClient.get(key);

					try
					{
						fs.writeFileSync(`${ uploads }${ local_filename }`, file.buffer);
						console.log("multer.upload.single file");
						console.log({ questionnaire });

						const parsed = JSON.parse(questionnaire);
						console.log("parsed", ".".repeat(50));
						console.log(parsed);

						const contacts = {};
						for(let c in parsed.contacts)
						{
							if(parsed.contacts[c].name === null)
							{
								contacts[c] = null;
							}
							else
							{
								contacts[c] = parsed.contacts[c];
							}
						}

						let payload = { ...parsed.main, ...contacts, ...{ head_person: parsed.head_person }, ...{ signatory_person: parsed.signatory_person }, };
						payload.mail_delivery_address_type = parseInt(payload.mail_delivery_address_type, 10);
						payload.questionnaire_sign_type = digital ? "eds" : "paper";

						payload.telephone = checkNullEmpty(payload.telephone) ? payload.telephone.replace(/[^0-9]/g, '') : null;
						payload.individual_executive_inn = checkNullEmpty(payload.individual_executive_inn) ?  payload.individual_executive_inn.replace(/[^0-9]/g, '') : null;
						payload.individual_executive_kpp = checkNullEmpty(payload.individual_executive_kpp) ? payload.individual_executive_kpp.replace(/[^0-9]/g, '') : null;
						payload.individual_executive_docdate = checkNullEmpty(payload.individual_executive_docdate) ? moment(payload.individual_executive_docdate).format("YYYY-MM-DD") : null;

						if(payload.head_person.middlename !== "" && payload.head_person.middlename !== null)
						{
							payload.head_person.no_middle_name = false;
						}
						else
						{
							payload.head_person.no_middle_name = true;
						}
						payload.head_person.identity_document.citizenship_code = payload.head_person.identity_document.citizenship.code.toString();
						payload.head_person.telephone = checkNullEmpty(payload.head_person.telephone) ? payload.head_person.telephone.replace(/[^0-9]/g, '') : null;
						payload.head_person.identity_document.issuedate = checkNullEmpty(payload.head_person.identity_document.issuedate) ? moment(payload.head_person.identity_document.issuedate).format("YYYY-MM-DD") : null;
						/*
						Запрос 2024-02-08 на удаление даты назначения и даты окончания полномочий

						payload.head_person.assignment_date = checkNullEmpty(payload.head_person.assignment_date) ? moment(payload.head_person.assignment_date).format("YYYY-MM-DD") : null;
						payload.head_person.credentials_dateend = checkNullEmpty(payload.head_person.credentials_dateend) ? moment(payload.head_person.credentials_dateend).format("YYYY-MM-DD") : null;
						*/
						payload.head_person.assignment_date = null;
						payload.head_person.credentials_dateend = null;

						if(payload.signatory_person.not_head_person)
						{
							if(payload.signatory_person.middlename !== "" && payload.signatory_person.middlename !== null)
							{
								payload.signatory_person.no_middle_name = false;
							}
							else
							{
								payload.signatory_person.no_middle_name = true;
							}
						}
						else
						{
							payload.signatory_person = { ...payload.signatory_person, ..._pick(payload.head_person, [
								"lastname", "firstname", "middlename", "no_middle_name", "jobtitle", "telephone", "email", "identity_document", 
								/*
								Запрос 2024-02-08 на удаление даты назначения и даты окончания полномочий

								"assignment_date", "credentials_dateend", "indefinite",
								*/
							]) };
						}
						payload.signatory_person.identity_document.citizenship_code = payload.signatory_person.identity_document.citizenship.code.toString();
						payload.signatory_person.telephone = checkNullEmpty(payload.signatory_person.telephone) ? payload.signatory_person.telephone.replace(/[^0-9]/g, '') : null;
						payload.signatory_person.identity_document.issuedate = checkNullEmpty(payload.signatory_person.identity_document.issuedate) ? moment(payload.signatory_person.identity_document.issuedate).format("YYYY-MM-DD") : null;
						payload.signatory_person.docdate = checkNullEmpty(payload.signatory_person.docdate) ? moment(payload.signatory_person.docdate).format("YYYY-MM-DD") : null;
						/*
						Запрос 2024-02-08 на удаление даты назначения и даты окончания полномочий

						payload.signatory_person.assignment_date = checkNullEmpty(payload.signatory_person.assignment_date) ? moment(payload.signatory_person.assignment_date).format("YYYY-MM-DD") : null;
						payload.signatory_person.credentials_dateend = checkNullEmpty(payload.signatory_person.credentials_dateend) ? moment(payload.signatory_person.credentials_dateend).format("YYYY-MM-DD") : null;
						*/
						payload.signatory_person.assignment_date = null;
						payload.signatory_person.credentials_dateend = null;

						payload.signatory_person.birthdate = checkNullEmpty(payload.signatory_person.birthdate) ? moment(payload.signatory_person.birthdate).format("YYYY-MM-DD") : null;

						const founder_persons = parsed.founder_persons;

						const hp_check = `${ payload.head_person.lastname !== undefined && payload.head_person.lastname !== null ? payload.head_person.lastname : "" }${ payload.head_person.firstname !== undefined && payload.head_person.firstname !== null ? payload.head_person.firstname : "" }${ payload.head_person.middlename !== undefined && payload.head_person.middlename !== null ? payload.head_person.middlename : "" }`.replace(/\s/, "").toLowerCase();
						const sp_check = `${ payload.signatory_person.lastname !== undefined && payload.signatory_person.lastname !== null ? payload.signatory_person.lastname : "" }${ payload.signatory_person.firstname !== undefined && payload.signatory_person.firstname !== null ? payload.signatory_person.firstname : "" }${ payload.signatory_person.middlename !== undefined && payload.signatory_person.middlename !== null ? payload.signatory_person.middlename : "" }`.replace(/\s/, "").toLowerCase();

						for(let i in founder_persons)
						{
							founder_persons[i].founder_number = parseInt(i, 10) + 1;
							founder_persons[i].founder_part = parseFloat(founder_persons[i].founder_part);
							/*
							Запрос 2024-02-13 на удаление телефона и адреса E-mail

							founder_persons[i].telephone = checkNullEmpty(founder_persons[i].telephone) ? founder_persons[i].telephone.replace(/[^0-9]/g, '') : null;
							*/
							founder_persons[i].telephone = null;
							founder_persons[i].email = null;
							founder_persons[i].identity_document.issuedate = checkNullEmpty(founder_persons[i].identity_document.issuedate) ? moment(founder_persons[i].identity_document.issuedate).format("YYYY-MM-DD") : null;
							founder_persons[i].identity_document.citizenship_code = founder_persons[i].identity_document.citizenship.code.toString();
							founder_persons[i].birthdate = checkNullEmpty(founder_persons[i].birthdate) ? moment(founder_persons[i].birthdate).format("YYYY-MM-DD") : null;

							if(founder_persons[i].middlename !== "" && founder_persons[i].middlename !== null)
							{
								founder_persons[i].no_middle_name = false;
							}
							else
							{
								founder_persons[i].no_middle_name = true;
							}

							const fp_check = `${ founder_persons[i].lastname !== undefined && founder_persons[i].lastname !== null ? founder_persons[i].lastname : "" }${ founder_persons[i].firstname !== undefined && founder_persons[i].firstname !== null ? founder_persons[i].firstname : "" }${ founder_persons[i].middlename !== undefined && founder_persons[i].middlename !== null ? founder_persons[i].middlename : "" }`.replace(/\s/, "").toLowerCase();

							console.log({ sp_check, hp_check, fp_check, });

							if(fp_check === sp_check)
							{
								founder_persons[i].telephone = payload.signatory_person.telephone;
								founder_persons[i].email = payload.signatory_person.email;
							}

							if(fp_check === hp_check)
							{
								founder_persons[i].telephone = payload.head_person.telephone;
								founder_persons[i].email = payload.head_person.email;
							}
						}

						payload = { ...payload, ...{ founder_persons }, ...{ 
							revenue_source_main: parsed.non_profit.fin_source_business, 
							revenue_source_donat: parsed.non_profit.fin_source_donate, 
							revenue_source_entrance_fee: parsed.non_profit.fin_source_fees, 
							revenue_source_other: parsed.non_profit.fin_source_another_description, 
							foreign_countries_financing: parsed.non_profit.foreign_payers, 
							purpose_use_la: parsed.non_profit.fin_goals_cars, 
							purpose_use_lkt: parsed.non_profit.fin_goals_trucks, 
							purpose_use_gt_sc: parsed.non_profit.fin_goals_special, 
							is_nko: parsed.main.nko ? true : false, 
						} };

						payload.financial_loan = checkNullEmpty(payload.financial_loan) ? parseFloat(payload.financial_loan.toString().replace(/[^0-9.]/g, '')) : null;
						payload.licenses = parsed.licenses;

						console.log({ id, path });
						console.log("payload", "*".repeat(100));
						console.log(payload);

						console.log("files", "^".repeat(50));
						console.log({ head_person_files: parsed.head_person_files });
						console.log({ delegation_files: parsed.delegation_files });
						console.log({ signatory_person_files: parsed.signatory_person_files });
						console.log({ signatory_corporate_files: parsed.signatory_corporate_files });

						const files_to_send = [];

						const files_groups = [
							{ name: "head_person", number: 1 }, 
							{ name: "delegation", number: 166, }, 
							{ name: "signatory_person", number: 23, }, 
							{ name: "signatory_corporate", number: 22, }
						];

						for(let g in files_groups)
						{
							if(parsed[`${ files_groups[g].name }_files`].length > 0)
							{
								let files_to_zip = [];
								for(let f in parsed[`${ files_groups[g].name }_files`])
								{
									const ext_regex = new RegExp("\.([0-9a-z]+)$", "i");
									const ext = parsed[`${ files_groups[g].name }_files`][f].name.match(ext_regex);

									files_to_zip.push({
										name: `${ files_groups[g].name }_file_${ f+1 }.${ ext[1] }`, 
										path: `${ uploads }${ parsed[`${ files_groups[g].name }_files`][f].filename }`, 
									});
								}

								let zip_filename = `${ client_jwt_decoded.acc_number }_${ files_groups[g].name }_files.zip`;
								await createZipFile(zip_filename, files_to_zip);
								files_to_send.push({ name: zip_filename, filename: zip_filename, number: files_groups[g].number, });
							}
						}

						if(digital)
						{
							const zip_filename = `${ client_jwt_decoded.acc_number }_questionnaire.zip`;
							await createZipFile(zip_filename, [{ 
								name: `${ client_jwt_decoded.acc_number }_questionnaire_${ timemark }.pdf`, 
								path: `${ uploads }${ client_jwt_decoded.acc_number }_questionnaire.pdf`, 
							}, 
							{ 
								name: local_filename, 
								path: `${ uploads }${ local_filename }`, 
							}]);

							files_to_send.push({ name: zip_filename, filename: zip_filename, number: 162 });
						}
						else
						{
							files_to_send.push({ name: local_filename, filename: local_filename, number: 161, });
						}

						console.log("files_to_send", ".".repeat(100));
						console.log(files_to_send);

						axios.put(path, payload, 
							{
								params: { name: id }, 
								headers: {
									"Authorization": `Bearer ${ crm_jwt }`, 
									"Content-Type": "application/json"
								}
							} 
						)
						.then((crm_response) => 
						{
							console.log("crm_response for", path);
							console.log(inspect(crm_response.data, true, null, true));

							eachSeries(files_to_send, (file_entry, callback) => 
							{
								if(fs.existsSync(`${ uploads }${ file_entry.filename }`))
								{
									const file_to_send_data = fs.readFileSync(`${ uploads }${ file_entry.filename }`);
									const data = new FormData();
									data.append("file", file_to_send_data, file_entry.name);

									console.log({ data });

									const file_upload_url = `${ process.env.CRM_API_HOST }/lk/document/upload/?entity=evo_client_questionnaire&documentTypeNumber=${ file_entry.number }&name=${ id }`;
									console.log({ file_upload_url });

									const headers = {
										"Content-Type": `multipart/form-data; boundary=${ data._boundary }`, 
										"Authorization": `Bearer ${ crm_jwt }`, 
									};

									console.log("API", "questionnaire", "send", { headers, "filename": file_entry.filename }, );

									axios.post(file_upload_url, data, 
									{
										headers, 
										withCredentials: true, 
									})
									.then(() => 
									{
										console.log("FILE", file_entry.filename, "SENT");
										callback();
									})
									.catch((crm_file_upload_error) => 
									{
										if(crm_file_upload_error.response !== undefined)
										{
											console.error("crm_file_upload_error", { status: crm_file_upload_error.response.status, data: crm_file_upload_error.response });
										}
										else
										{
											console.error({ crm_file_upload_error });
										}
										callback();
									});
								}
								else
								{
									callback();
								}
							}, async () => 
							{
								const existed_files = fs.readdirSync(uploads);
								existed_files.forEach(file => 
								{
									if(file.indexOf(client_jwt_decoded.acc_number) === 0)
									{
										fs.unlinkSync(`${ uploads }${ file }`);
									}
								});

								await RedisClient.del(key);
								res.status(200).json({ payload, id, digital });
								resolve();
							});
						})
						.catch((crm_send_error) => 
						{
							if(crm_send_error.response !== undefined)
							{
								console.error("crm_send_error", { status: crm_send_error.response.status, data: crm_send_error.response.data });
								console.error({ payload });
							}
							else
							{
								console.error({ crm_send_error });
							}

							res.status(500).json({ payload, id, digital });
							resolve();
						});

						//res.status(500).json({ payload });
					}
					catch(upload_single_error)
					{
						console.error("upload_single_error");
						console.error(upload_single_error);

						res.status(500).json({ id, digital });
						resolve();
					}
				});
			}
			else
			{
				res.status(403).send();
				resolve();
			}
		}
	});
}

export const config = {
	api: {
		bodyParser: false
	}
}