import React from "react";
import Link from "next/link";
import { SpinnerCircular } from "spinners-react";
import moment from "moment";
import dynamic from 'next/dynamic';
import { concatSeries } from 'async';
import fileDownload from 'js-file-download';
import * as Sentry from "@sentry/nextjs";

import FormMessage from "./FormMessage";
import { downloadQuestionnaire, uploadSignedFile } from "../../../actions";
//import { generateSignature } from "../../../utils/digital_signature";


export default class DigitalCertificates extends React.Component
{
	constructor(props)
	{
		super(props);

		this.state = {
			loading: true, 
			certificates: [], 
			certificates_error: null, 
			certificate_selected: undefined, 
			signing: false, 
			show_all: false, 
		};
		this.cryptopro = null;
	}

	async componentDidMount()
	{
		const { company, main, head_person } = this.props;
		//console.log({ company, main });
		//console.log("DC", "CDM");

		const { CryptoPro } = await import('ruscryptojs');

		this.cryptopro = new CryptoPro();
		this.cryptopro.init()
		.then((info) => 
		{
			//console.log('Initialized', info);
//			console.log('-'.repeat(20));
//			for(let i in this.cryptopro)
//			{
//				console.log(i);
//			}
//			console.log('-'.repeat(20));

			this.cryptopro.listCertificates()
			.then((certificates_list) => 
			{
				console.log({ certificates_list });

				console.log("all certificates", JSON.stringify(certificates_list));
				Sentry.captureMessage("Client digital sign step, list of all digital certificates");

				concatSeries(certificates_list, (certificate, callback) => 
				{
					//console.log(certificate.id, certificate.name);

					this.cryptopro.certificateInfo(certificate.id)
					.then((cert) => 
					{
						const errors = [];
						let apply = true;

						console.log("certificate", JSON.stringify(cert));
						console.log("company", JSON.stringify(company));

						//console.log({ cert });
						if(cert.Subject['OGRNIP'] !== undefined && cert.Subject['OGRNIP'] !== null && cert.Subject['OGRNIP'] !== "")
						{
							if(cert.Subject['INN'] !== undefined && cert.Subject['INN'] !== null && cert.Subject['INN'] !== "")
							{
								if(main.inn !== cert.Subject['INN'])
								{
									errors.push('inn');
								}
							}
							else
							{
								apply = false;
							}
						}
						else
						{
							if(cert.Subject['INNLE'] !== undefined && cert.Subject['INNLE'] !== null && cert.Subject['INNLE'] !== "")
							{
								if(main.inn !== cert.Subject['INNLE'])
								{
									errors.push('inn');
								}
							}
							else
							{
								apply = false;
							}
						}

						let owner_valid = true;
						const fields = [ "lastname", "firstname", "middlename", ];
						const cert_owner = `${ cert.Subject['SN']} ${ cert.Subject['G']}`.toUpperCase();

						for(let i in fields)
						{
							if(head_person[fields[i]] !== null && head_person[fields[i]] !== "")
							{
								if(cert_owner.indexOf(head_person[fields[i]].toUpperCase().trim()) < 0)
								{
									owner_valid = false;
								}
							}
						}

						if(!owner_valid)
						{
							errors.push('name');
						}

						if(cert.ValidToDate !== null && cert.ValidToDate !== undefined && cert.ValidToDate !== "")
						{
							if(moment(cert.ValidToDate) < moment())
							{
								errors.push('date');
							}
						}
						else
						{
							errors.push('date');
						}

						if(!cert.IsValid)
						{
							errors.push('invalid');
						}
						if(apply)
						{
							callback(null, [ { id: certificate.id, fields: cert.Subject, valid_to_date: moment(cert.ValidToDate).format("DD.MM.YYYY"), errors } ]);
						}
						else
						{
							callback(null, []);
						}
					})
					.catch((error_certificates_info) => 
					{
						Sentry.captureMessage("Client digital sign step error");

						console.error({ error_certificates_info });
						this.setState({ loading: false, certificates_error: "CERTIFICATES" });
					});		
				}, (error, certificates) => 
				{
					console.log("applicable certificates", JSON.stringify(certificates));
					Sentry.captureMessage("Client digital sign step, list of applicable digital certificates");

					if(certificates.length === 0)
					{
						this.setState({ loading: false, certificates_error: "INVALID" });
					}
					else
					{
						const list = [];
						let valid_certificate_exists = false;

						for(let i in certificates) { if(certificates[i].errors.length === 0) { list.push(certificates[i]); valid_certificate_exists = true; } }
						for(let i in certificates) { if(certificates[i].errors.length !== 0) { list.push(certificates[i]); } }

						const update = { loading: false, certificates: list, certificates_error: null };
						if(list[0] !== undefined)
						{
							if(list[0].errors.length === 0)
							{
								update.certificate_selected = list[0];
							}
						}

						if(!valid_certificate_exists)
						{
							update.certificates_error = "INVALID";
						}

						this.setState(update);
					}
				});
			})
			.catch((error_certificates_list) => 
			{
				console.error({ error_certificates_list });
				this.setState({ loading: false, certificates_error: "CERTIFICATES" });
			});
		})
		.catch((error_init) => 
		{
			console.error({ error_init });
			this.setState({ loading: false, certificates_error: "NOT_INSTALLED" });
		});	
	}

	_sign = () => 
	{
		this.setState({ signing: true }, () => 
		{
			const { company, main, onSignDigital } = this.props;
			const filename = `${ main.inn }_questionnaire_${ moment().format("DDMMYYYY_HHmmss") }.sig`;
	
			downloadQuestionnaire({ filename, download: false, base64: true })
			.then(({ file }) => 
			{
				let file_to_sign = file;

				const now = moment().format("DDMMYYYY_HHmmss");
				this.cryptopro.signData(file_to_sign, this.state.certificate_selected.id)
				.then(signature => 
				{
					//console.log({ signature });

					let signature_file = new File([ signature ], filename);
					uploadSignedFile(signature_file, company.questionnaire_id, true)
					.then(() => 
					{
						onSignDigital();
					})
					.catch(() => 
					{
						this.setState({ signing: false });
					});
				})
				.catch((error_sign) => 
				{
					console.error({ error_sign });
					this.setState({ signing: false });
				})
			})
			.catch((e) => 
			{
				console.error("exception on sign");
				console.error(e);
			});
		});
	}

	render()
	{
		const { company, main, head_person } = this.props;
		const { loading, certificates, certificates_error, certificate_selected, signing, show_all } = this.state;
		//console.log("render()", { certificates });

		console.log({ certificates_error });

		if(loading)
		{ 
			return (
				<div style={{ minHeight: 200, display: "flex", justifyContent: "center", alignItems: "center", }}>
					<SpinnerCircular size={ 90 } thickness={ 51 } speed={ 100 } color="rgba(28, 1, 169, 1)" secondaryColor="rgba(236, 239, 244, 1)" />
				</div>
			); 
		}
		else
		{
			return (
				<>
					{ certificates_error !== null && (
						<>
							{ (certificates_error === "NOT_INSTALLED" || certificates_error === "CERTIFICATES") && (
								<FormMessage type="moderate" title="Внимание!" message={ <>
									Плагин КриптоПРО не установлен или не активирован. Посмотрите <a style={{ color: "#fff", textDecoration: "underline", }} href={ `${ process.env.NEXT_PUBLIC_MAIN_SITE }/upload/docs/anketa-sign.pdf` }>инструкцию</a> как установить, активировать и проверить работу плагина КриптоПро.<br/>
									<br/>
									После активации плагина, пожалуйста, обновите страницу.
								</> }/>
							) }
							{ certificates_error === "INVALID" && (
								<FormMessage type="moderate" title="Внимание!" message={ <>
									Анкету необходимо подписать по ЭЦП сертификатом юридического лица с ИНН: <br/>
									{ main.inn }, выданного: { head_person.lastname } { head_person.firstname } { head_person.middlename }. <br/>
									Такой сертификат не найден!<br/><br/>
									Если Вы уверены в наличии такого сертификата:
									<ol style={{ listStyle: "decimal", padding: "revert" }}>
										<li>Проверьте, вставлен ли ключ с этим сертификатом.</li>
										<li>Проверьте возможность подписания этим сертификатом с помощью средства <a style={{ color: "#fff", textDecoration: "underline", }} href="https://cryptopro.ru/sites/default/files/products/cades/demopage/cades_bes_sample.html">проверки КриптоПро</a>.</li>
										<li>Возможно, сертификат нужно установить. <a style={{ color: "#fff", textDecoration: "underline", }} href={ `${ process.env.NEXT_PUBLIC_MAIN_SITE }/upload/docs/anketa-sign.pdf` }>Воспользуйтесь инструкцией</a>.</li>
									</ol>
								</> }/>
							) }
							{ certificates_error === "MISMATCH" && (
								<FormMessage type="moderate" title="Внимание!" message={ <>Подписант не соответствует указанному подписанту в анкете.</> }/>
							) }
						</>
						)
					}
					{ certificates.length > 0 && (
						<>
							<div className="feed">
								<p>Список сертификатов, доступных на Вашем компьютере:</p>
								<div className="feed_list">

									{ certificates.slice(0, show_all ? certificates.length : 2).map((certificate, index) => (
										<div className={`form_field checkbox digital_certificates_status ${ certificate.errors.length > 0 ? "error" : "" } ${ certificates.length > 1 && !show_all && index === 1 ? "show_all_holder" : ""}`} key={ index }>
											<input type="radio" 
												hidden="" 
												id={ `certificate_${ certificate.id }` } 
												name={ `certificate_${ certificate.id }` } 
												checked={ certificate_selected !== undefined && certificate_selected.id === certificate.id ? true : false } 
												onChange={ () => { this.setState({ certificate_selected: certificate }) } }
											/>
											<label htmlFor={ `certificate_${ certificate.id }` }>
												<div className="feed_item user">
													<img src="/assets/images/icons/avatar.svg" alt="" />
													<div>
														<p className="item_title">{ certificate.fields['CN'].replace(/"/g, '') }</p>
														<p className="item_desc">
															{ certificate.fields['SN'] ? (<span>{ certificate.fields['SN'] } { certificate.fields['G'] }</span>) : null }
														</p>
														<p className="item_desc">
															<span>ИНН { certificate.fields['INNLE'] !== undefined && certificate.fields['INNLE'] !== null ? certificate.fields['INNLE'] : certificate.fields['INN'] }</span>
														</p>
														<p className="item_desc">
															{ certificate.fields['OGRNIP'] && (<span>ОГРНИП { certificate.fields['OGRNIP'] }</span>) } 
															{ certificate.fields['OGRN'] && (<span>ОГРН { certificate.fields['OGRN'] }</span>) } 
														</p>
														<p className="item_desc">
															<span>Подпись действительна до { certificate.valid_to_date }</span> 
														</p>
													</div>
													{ certificate.errors.length > 0 && (
														<div>
															<p className="item_title">&nbsp;</p>
															{ certificate.errors.indexOf("name") > -1 ? <p className="item_desc" style={{ color: "#A8026B" }}>Не соответствует ФИО</p> : <p className="item_desc">&nbsp;</p>}
															{ certificate.errors.indexOf("inn") > -1 ? <p className="item_desc" style={{ color: "#A8026B" }}>Не соответствует ИНН</p> : <p className="item_desc">&nbsp;</p>}
															<p className="item_desc">&nbsp;</p>
															{ certificate.errors.indexOf("date") > -1 ? <p className="item_desc" style={{ color: "#A8026B" }}>{ certificate.errors.indexOf('date') > 1 ? "Срок действия закончился" : certificate.errors.indexOf('invalid') > 1 ? "Сертификат недействителен или нарушена цепочка сертификации" : null }</p> : <p className="item_desc">&nbsp;</p>}
															{ certificate.errors.length === 1 && certificate.errors[0] === "invalid" && (<p className="item_desc" style={{ color: "#A8026B" }}>Сертификат недействителен или нарушена цепочка сертификации</p>) }
														</div>
													) }
												</div>
											</label>
											{ certificates.length > 1 && !show_all && index === 1 && (
												<div className="show_all" onClick={ () => this.setState({ show_all: true }) }><span>Посмотреть все</span></div>
											) }
										</div>
									)) }

								</div>
							</div>
							<div className="action" style={{marginBottom: "20px"}}>
								<div></div>
								<button 
									type="submit" 
									className="button button-blue" 
									disabled={ certificate_selected !== null && certificate_selected !== undefined ? false : true } 
									onClick={ this._sign } 
									style={{ minWidth: "250px" }} 
								>
									{ signing ? (
										<SpinnerCircular size={24} thickness={100} speed={100} color="rgba(255, 255, 255, 1)" secondaryColor="rgba(255, 255, 255, 0.5)" style={{ marginTop: "4px" }}/>
									) : "Подписать выбранной подписью" }
								</button>
							</div>
						</>
					) }
				</>
			)
		}
	}
}