Загрузка данных


(function () {
	'use strict';

	var CAPTCHA_SITEKEY = 'ysc1_2AEEpAK4WRu0mf1BpGOdcfhiKbrfn4XHn5JpdXrR9c3006f7';
	var API_BASE = '/fuel/qr';
	var CLIENT_ID_KEY = 'fuelQrClientId';
	var SESSION_UNTIL_KEY = 'fuelQrSessionUntil';
	var PLATE_LATIN = 'ABEKMHOPCTYX';
	var PLATE_CYRILLIC = 'АВЕКМНОРСТУХ';
	var PLATE_STANDARD_RE = /^[АВЕКМНОРСТУХ][0-9]{3}[АВЕКМНОРСТУХ]{2}[0-9]{2,3}$/;
	var PLATE_ALLOWED_RE = /^[0-9A-ZА-ЯЁ]{3,10}$/;

	var state = {
		authMode: '',
		captchaScriptPromise: null,
		maxScriptPromise: null,
		widgetId: null,
		clientId: null,
		carPlate: '',
		plateFormatConfirmed: false,
		pendingPlateConfirmation: '',
		fuelTypes: [],
		outOfStockMessage: '',
		currentTicket: null,
	};

	var els = {};

	function qs(selector) {
		return document.querySelector(selector);
	}

	function initElements() {
		els.message = qs('[data-message]');
		els.statusPill = qs('[data-status-pill]');
		els.loadingTitle = qs('[data-loading-title]');
		els.loadingText = qs('[data-loading-text]');
		els.unsupportedTitle = qs('[data-unsupported-title]');
		els.unsupportedText = qs('[data-unsupported-text]');
		els.outOfStockMessage = qs('[data-out-of-stock-message]');
		els.retryCaptcha = qs('[data-retry-captcha]');
		els.plateForm = qs('[data-plate-form]');
		els.plateInput = qs('[data-plate-input]');
		els.plateSubmit = qs('[data-plate-submit]');
		els.fuelForm = qs('[data-fuel-form]');
		els.fuelSelect = qs('[data-fuel-select]');
		els.createSubmit = qs('[data-create-submit]');
		els.backToPlate = qs('[data-back-to-plate]');
		els.ticket = qs('[data-ticket]');
		els.ticketPlate = qs('[data-ticket-plate]');
		els.ticketFuel = qs('[data-ticket-fuel]');
		els.ticketQr = qs('[data-ticket-qr]');
		els.ticketLink = qs('[data-ticket-link]');
		els.newRequest = qs('[data-new-request]');
		els.share = qs('[data-share]');
	}

	function showStep(name) {
		Array.prototype.forEach.call(document.querySelectorAll('[data-step]'), function (node) {
			node.classList.toggle('is-active', node.getAttribute('data-step') === name);
		});
	}

	function setStatus(text) {
		els.statusPill.textContent = text;
	}

	function showMessage(text, type) {
		els.message.textContent = text;
		els.message.className = 'notice notice--' + (type || 'info');
		els.message.hidden = !text;
	}

	function clearMessage() {
		showMessage('');
	}

	function debugBeacon(eventName, details) {
		var url = API_BASE + '/clientapp-debug.gif'
			+ '?event=' + encodeURIComponent(eventName || 'unknown')
			+ '&location=' + encodeURIComponent(window.location.href)
			+ '&auth_mode=' + encodeURIComponent(state.authMode || '')
			+ '&client_id=' + encodeURIComponent(state.clientId || '')
			+ '&details=' + encodeURIComponent(details || '')
			+ '&_=' + Date.now();
		var img = new Image();
		img.src = url;
	}

	function setBusy(button, busy) {
		if (!button) {
			return;
		}
		button.disabled = !!busy;
		button.setAttribute('aria-busy', busy ? 'true' : 'false');
		button.classList.toggle('is-loading', !!busy);
	}

	function getStoredValue(key) {
		try {
			return window.localStorage.getItem(key) || '';
		} catch (e) {
			return '';
		}
	}

	function setStoredValue(key, value) {
		try {
			window.localStorage.setItem(key, value);
		} catch (e) {
			// LocalStorage can be disabled in embedded webviews.
		}
	}

	function removeStoredValue(key) {
		try {
			window.localStorage.removeItem(key);
		} catch (e) {
			// LocalStorage can be disabled in embedded webviews.
		}
	}

	function isValidClientId(value) {
		return /^[A-Za-z0-9._:-]{8,128}$/.test(value || '');
	}

	function readStoredClientId() {
		var existing = getStoredValue(CLIENT_ID_KEY);
		return isValidClientId(existing) ? existing : '';
	}

	function getStoredSessionUntil() {
		var value = parseInt(getStoredValue(SESSION_UNTIL_KEY), 10);
		return isFinite(value) ? value : 0;
	}

	function markSessionActive(ttl) {
		var seconds = parseInt(ttl, 10);
		if (!isFinite(seconds) || seconds <= 0) {
			clearSessionMarker();
			return;
		}
		setStoredValue(SESSION_UNTIL_KEY, String(Date.now() + seconds * 1000));
	}

	function clearSessionMarker() {
		removeStoredValue(SESSION_UNTIL_KEY);
	}

	function shouldCheckSession() {
		return isValidClientId(state.clientId) && getStoredSessionUntil() > Date.now();
	}

	function readAuthMode() {
		var mode = '';
		var rawMode = '';
		try {
			rawMode = new URLSearchParams(window.location.search).get('mode') || '';
		} catch (e) {
			rawMode = '';
		}
		mode = rawMode.split('?')[0].split('&')[0];

		if (mode === '') {
			debugBeacon('missing_mode_default_max');
			return 'max-mini-app';
		}
		if (/^(web|max-mini-app|superapp)$/.test(mode)) {
			if (mode !== rawMode) {
				debugBeacon('mode_recovered_from_dirty_query', 'raw=' + rawMode + ';mode=' + mode);
			}
			return mode;
		}
		debugBeacon('invalid_mode', 'mode=' + rawMode);
		return '';
	}

	function openForm() {
		clearMessage();
		showLoading('Проверяем остатки', 'Получаем доступные виды топлива.');

		return loadFuelTypes(true).then(function (types) {
			if (!types.length) {
				showEmptyStock();
				return false;
			}
			setStatus('Форма');
			showStep('plate');
			els.plateInput.focus();
			return true;
		}).catch(function (err) {
			if (err && err.sessionExpired) {
				startAuthFlow();
				return false;
			}
			setStatus('Ошибка');
			debugBeacon('open_form_failed', err.message || '');
			showUnsupported('Не удалось открыть форму', 'Не удалось получить данные для выбора топлива.', err.message || 'Не удалось получить данные для выбора топлива.');
			return false;
		});
	}

	function showEmptyStock() {
		clearMessage();
		setStatus('Нет топлива');
		if (els.outOfStockMessage) {
			els.outOfStockMessage.textContent = state.outOfStockMessage;
		}
		showStep('empty-stock');
	}

	function showUnsupported(title, text, message) {
		setStatus('Недоступно');
		if (els.unsupportedTitle) {
			els.unsupportedTitle.textContent = title || 'Режим недоступен';
		}
		if (els.unsupportedText) {
			els.unsupportedText.textContent = text || 'Откройте страницу другим способом.';
		}
		showStep('unsupported');
		showMessage(message || text || title || 'Режим недоступен', 'error');
	}

	function getWebApp() {
		return window.WebApp || null;
	}

	function loadMaxScript() {
		if (getWebApp()) {
			return Promise.resolve();
		}
		if (state.maxScriptPromise) {
			return state.maxScriptPromise;
		}

		state.maxScriptPromise = new Promise(function (resolve, reject) {
			var script = document.createElement('script');
			var timer = window.setTimeout(function () {
				state.maxScriptPromise = null;
				reject(new Error('MAX Bridge не загрузился.'));
			}, 10000);

			script.src = 'https://st.max.ru/js/max-web-app.js';
			script.async = true;
			script.onload = function () {
				window.clearTimeout(timer);
				resolve();
			};
			script.onerror = function () {
				window.clearTimeout(timer);
				state.maxScriptPromise = null;
				reject(new Error('MAX Bridge не загрузился.'));
			};
			document.head.appendChild(script);
		});

		return state.maxScriptPromise;
	}

	function showLoading(title, text) {
		if (els.loadingTitle) {
			els.loadingTitle.textContent = title || 'Проверяем сессию';
		}
		if (els.loadingText) {
			els.loadingText.textContent = text || 'Это займет несколько секунд.';
		}
		showStep('loading');
	}

	function makeClientId() {
		if (window.crypto && typeof window.crypto.randomUUID === 'function') {
			return window.crypto.randomUUID();
		}

		if (window.crypto && typeof window.crypto.getRandomValues === 'function') {
			var bytes = new Uint8Array(16);
			window.crypto.getRandomValues(bytes);
			return Array.prototype.map.call(bytes, function (b) {
				return ('0' + b.toString(16)).slice(-2);
			}).join('');
		}

		return String(Date.now()) + '-' + String(Math.random()).slice(2);
	}

	function getClientId() {
		var existing = readStoredClientId();
		if (existing) {
			return existing;
		}

		var created = makeClientId();
		setStoredValue(CLIENT_ID_KEY, created);
		return created;
	}

	function normalizePlate(value) {
		var input = String(value || '').trim().toUpperCase();
		var out = '';
		var i;
		var ch;
		var idx;

		for (i = 0; i < input.length; i += 1) {
			ch = input.charAt(i);
			idx = PLATE_LATIN.indexOf(ch);
			out += idx >= 0 ? PLATE_CYRILLIC.charAt(idx) : ch;
		}

		return out.replace(/[^0-9A-ZА-ЯЁ]/g, '');
	}

	function isStandardPlate(value) {
		return PLATE_STANDARD_RE.test(value || '');
	}

	function isAllowedPlate(value) {
		return PLATE_ALLOWED_RE.test(value || '');
	}

	function formatDate(value) {
		var date = new Date(value);
		if (Number.isNaN(date.getTime())) {
			return value || '';
		}
		return date.toLocaleString('ru-RU', {
			day: '2-digit',
			month: '2-digit',
			year: 'numeric',
			hour: '2-digit',
			minute: '2-digit',
		});
	}

	function buildShareText(ticket) {
		return [
			'QR-код на топливо',
			'Госномер: ' + ticket.car_plate,
			'Топливо: ' + ticket.fuel_type_title,
		].join('\n');
	}

	function isValidTicket(ticket) {
		return !!(
			ticket
			&& ticket.qr_png_base64
		);
	}

	function qrPngFile(ticket) {
		var binary = window.atob(ticket.qr_png_base64);
		var bytes = new Uint8Array(binary.length);
		var i;
		var blob;

		for (i = 0; i < binary.length; i += 1) {
			bytes[i] = binary.charCodeAt(i);
		}

		blob = new Blob([bytes], { type: 'image/png' });
		if (typeof window.File !== 'function') {
			return null;
		}

		return new File([blob], 'fuel-qr-' + ticket.car_plate + '.png', { type: 'image/png' });
	}

	function shareDataForTicket(ticket) {
		var text = buildShareText(ticket);
		var data = {
			title: 'QR-код на топливо',
			text: text,
			url: ticket.deeplink,
		};
		var file;

		try {
			file = qrPngFile(ticket);
			if (
				file
				&& typeof window.navigator.canShare === 'function'
				&& window.navigator.canShare({ files: [file] })
			) {
				data.files = [file];
			}
		} catch (e) {
			// File sharing support differs across mobile webviews; text and link sharing remains useful.
		}

		return data;
	}

	function updateShareButton() {
		els.share.hidden = !(state.currentTicket && window.navigator.share);
	}

	function resetCaptcha() {
		if (window.smartCaptcha && state.widgetId !== null) {
			window.smartCaptcha.reset(state.widgetId);
		}
		if (els.retryCaptcha) {
			els.retryCaptcha.hidden = true;
		}
	}

	function request(path, options) {
		var params = options || {};
		params.headers = Object.assign({ 'Content-Type': 'application/json' }, params.headers || {});
		params.credentials = 'same-origin';

		return window.fetch(API_BASE + path, params)
			.then(function (res) {
				return res.json().catch(function () {
					return { status: 'fail', message: 'Некорректный ответ сервера' };
				}).then(function (json) {
					if (res.status === 401 || (res.status === 403 && json.message && json.message.indexOf('Сессия') >= 0)) {
						var expired = new Error(json.message || 'Сессия истекла');
						expired.sessionExpired = true;
						clearSessionMarker();
						resetCaptcha();
						throw expired;
					}
					if (!res.ok || json.status !== 'ok') {
						throw new Error(json.message || 'Ошибка обработки запроса');
					}
					return json.data || {};
				});
			});
	}

	function startCaptchaSession(token) {
		setStatus('Открытие сессии');
		clearMessage();
		showLoading('Открываем сессию', 'Проверяем результат капчи.');

		return request('/session', {
			method: 'POST',
			body: JSON.stringify({
				captcha_token: token,
				client_id: state.clientId,
			}),
		}).then(function (data) {
			markSessionActive(data.ttl);
			resetCaptcha();
			openForm();
		}).catch(function (err) {
			clearSessionMarker();
			resetCaptcha();
			showCaptchaGate();
			showMessage(err.message, 'error');
			if (els.retryCaptcha) {
				els.retryCaptcha.hidden = false;
			}
		});
	}

	function showCaptchaGate() {
		setStatus('Проверка');
		showStep('captcha');
		loadCaptchaScript().then(onCaptchaLoad).catch(function () {
			showMessage('Не удалось загрузить проверку. Проверьте соединение.', 'error');
			if (els.retryCaptcha) {
				els.retryCaptcha.hidden = false;
			}
		});
	}

	function loadCaptchaScript() {
		if (window.__fuelCaptchaReady) {
			return Promise.resolve();
		}
		if (state.captchaScriptPromise) {
			return state.captchaScriptPromise;
		}

		window.onFuelCaptchaLoad = function () {
			window.__fuelCaptchaReady = true;
			if (window.FuelQrPage) {
				window.FuelQrPage.onCaptchaLoad();
			}
		};

		state.captchaScriptPromise = new Promise(function (resolve, reject) {
			var script = document.createElement('script');
			script.src = 'https://smartcaptcha.cloud.yandex.ru/captcha.js?render=onload&onload=onFuelCaptchaLoad';
			script.async = true;
			script.defer = true;
			script.onload = function () {
				resolve();
			};
			script.onerror = function () {
				state.captchaScriptPromise = null;
				reject(new Error('captcha load failed'));
			};
			document.head.appendChild(script);
		});

		return state.captchaScriptPromise;
	}

	function checkSessionStatus() {
		setStatus('Проверка');
		showLoading('Проверяем сессию', 'Если проверка еще действует, форма откроется автоматически.');

		return request('/session/status', { method: 'GET', headers: {} }).then(function (data) {
			if ((data.auth_mode || 'web') !== state.authMode) {
				debugBeacon('session_auth_mode_mismatch', 'server=' + (data.auth_mode || 'web') + ';client=' + state.authMode);
				clearSessionMarker();
				startAuthFlow();
				return;
			}
			markSessionActive(data.ttl);
			openForm();
		}).catch(function (err) {
			clearSessionMarker();
			clearMessage();
			if (err && err.sessionExpired) {
				startAuthFlow();
				return;
			}
			startAuthFlow();
		});
	}

	function startMaxMiniAppSession() {
		setStatus('MAX');
		clearMessage();
		showLoading('Проверяем доступ', 'Ожидаем данные MAX.');

		loadMaxScript().then(function () {
			var webApp = getWebApp();
			if (!webApp) {
				debugBeacon('max_webapp_missing');
				throw new Error('Откройте страницу внутри MAX.');
			}
			if (!webApp.initData) {
				debugBeacon('max_init_data_missing');
				throw new Error('Откройте страницу внутри MAX.');
			}
			if (typeof webApp.requestContact !== 'function') {
				debugBeacon('max_request_contact_missing');
				throw new Error('Откройте страницу внутри MAX.');
			}

			showLoading('Проверяем доступ', 'Запрашиваем номер телефона.');
			return Promise.resolve(webApp.requestContact()).then(function (result) {
				return {
					webApp: webApp,
					result: result,
				};
			});
		}).then(function (context) {
			var result = context.result;
			if (result && result.error) {
				debugBeacon('max_contact_denied_or_failed', result.error);
				throw new Error('Для доступа нужно разрешить передачу номера телефона.');
			}
			var contact = result && result.contact ? result.contact : result;
			return request('/session/max', {
				method: 'POST',
				body: JSON.stringify({
					client_id: state.clientId,
					init_data: context.webApp.initData,
					contact: contact,
					platform: context.webApp.platform,
					version: context.webApp.version,
				}),
			});
		}).then(function (data) {
			markSessionActive(data.ttl);
			openForm();
		}).catch(function (err) {
			clearSessionMarker();
			debugBeacon('max_session_failed', err.message || '');
			showUnsupported('Не удалось открыть MAX-режим', err.message || 'Повторите попытку позже.', err.message || 'Не удалось открыть MAX-режим.');
		});
	}

	function startUnsupportedSuperApp() {
		showUnsupported('Режим приложения не поддержан', 'Авторизация superapp будет добавлена позже.', 'Режим приложения пока не поддержан.');
	}

	function startAuthFlow() {
		if (state.authMode === 'web') {
			showCaptchaGate();
			return;
		}
		if (state.authMode === 'max-mini-app') {
			startMaxMiniAppSession();
			return;
		}
		if (state.authMode === 'superapp') {
			startUnsupportedSuperApp();
			return;
		}
		debugBeacon('auth_flow_unhandled_mode', state.authMode || '');
		showUnsupported('Не удалось выбрать сценарий авторизации', 'Режим страницы определен, но для него не найден обработчик.', 'Не найден обработчик режима: ' + (state.authMode || 'пусто') + '.');
	}

	function onCaptchaLoad() {
		var container = document.getElementById('captcha-container');
		if (state.widgetId !== null) {
			return;
		}
		if (!window.smartCaptcha || !container) {
			return;
		}

		state.widgetId = window.smartCaptcha.render(container, {
			sitekey: CAPTCHA_SITEKEY,
			hl: 'ru',
			callback: startCaptchaSession,
		});

		window.smartCaptcha.subscribe(state.widgetId, 'network-error', function () {
			showMessage('Не удалось загрузить проверку. Проверьте соединение.', 'error');
			els.retryCaptcha.hidden = false;
		});
		window.smartCaptcha.subscribe(state.widgetId, 'javascript-error', function () {
			showMessage('Проверка временно недоступна. Обновите страницу.', 'error');
			els.retryCaptcha.hidden = false;
		});
		window.smartCaptcha.subscribe(state.widgetId, 'token-expired', function () {
			resetCaptcha();
			showMessage('Время проверки истекло. Пройдите ее заново.', 'error');
			els.retryCaptcha.hidden = false;
		});
	}

	function loadFuelTypes(force) {
		if (!force && state.fuelTypes.length) {
			return Promise.resolve(state.fuelTypes);
		}

		return request('/fuel-types', { method: 'GET', headers: {} }).then(function (data) {
			state.fuelTypes = data.fuel_types || [];
			state.outOfStockMessage = data.out_of_stock_message || '';
			return state.fuelTypes;
		});
	}

	function fillFuelTypes(types) {
		els.fuelSelect.innerHTML = '';
		var placeholder = document.createElement('option');
		placeholder.value = '';
		placeholder.textContent = 'Выберите';
		placeholder.selected = true;
		placeholder.disabled = true;
		els.fuelSelect.appendChild(placeholder);

		types.forEach(function (item) {
			var option = document.createElement('option');
			option.value = item.id;
			option.textContent = item.title;
			els.fuelSelect.appendChild(option);
		});
	}

	function renderTicket(ticket, message) {
		if (!isValidTicket(ticket)) {
			state.currentTicket = null;
			updateShareButton();
			showMessage('Не удалось получить данные QR-кода. Попробуйте позже.', 'error');
			setStatus('Ошибка');
			return;
		}

		state.currentTicket = ticket;
		els.ticketPlate.textContent = ticket.car_plate;
		els.ticketFuel.textContent = ticket.fuel_type_title;
		els.ticketQr.src = 'data:image/png;base64,' + ticket.qr_png_base64;
		els.ticketLink.href = ticket.deeplink;
		els.ticket.hidden = false;
		updateShareButton();
		showMessage(message || 'QR-код готов.', ticket.reused ? 'info' : 'success');
		setStatus('QR-код');
		showStep('result');
	}

	function onPlateSubmit(event) {
		event.preventDefault();
		clearMessage();

		if (!state.fuelTypes.length) {
			showEmptyStock();
			return;
		}

		var normalized = normalizePlate(els.plateInput.value);
		els.plateInput.value = normalized;
		if (!isAllowedPlate(normalized)) {
			state.pendingPlateConfirmation = '';
			state.plateFormatConfirmed = false;
			showMessage('Недопустимый формат госномера. Укажите от 3 до 10 букв или цифр.', 'error');
			return;
		}

		var isStandard = isStandardPlate(normalized);
		if (!isStandard && state.pendingPlateConfirmation !== normalized) {
			state.pendingPlateConfirmation = normalized;
			state.plateFormatConfirmed = false;
			showMessage('Номер ' + normalized + ' не похож на стандартный российский госномер. Если номер указан верно, нажмите «Проверить номер» ещё раз.', 'warning');
			return;
		}

		state.carPlate = normalized;
		state.plateFormatConfirmed = !isStandard;
		state.pendingPlateConfirmation = '';
		setBusy(els.plateSubmit, true);

		request('/plate/check', {
			method: 'POST',
			body: JSON.stringify({
				car_plate: normalized,
				plate_format_confirmed: state.plateFormatConfirmed,
			}),
		}).then(function (data) {
			if ((data.state === 'active' || data.state === 'active_own') && data.ticket) {
				renderTicket(data.ticket, 'По этому госномеру уже есть активный QR-код.');
				return;
			}
			if (data.state === 'blocked') {
				showMessage('Новый QR-код по этому госномеру будет доступен: ' + formatDate(data.next_create_at), 'error');
				return;
			}

			fillFuelTypes(state.fuelTypes);
			setStatus('Топливо');
			showStep('fuel');
		}).catch(function (err) {
			if (err && err.sessionExpired) {
				startAuthFlow();
				return;
			}
			showMessage(err.message, 'error');
		}).finally(function () {
			setBusy(els.plateSubmit, false);
		});
	}

	function onFuelSubmit(event) {
		event.preventDefault();
		clearMessage();

		if (!state.fuelTypes.length) {
			showEmptyStock();
			return;
		}

		if (!els.fuelSelect.value) {
			showMessage('Выберите вид топлива.', 'error');
			els.fuelSelect.focus();
			return;
		}

		setBusy(els.createSubmit, true);

		request('/create', {
			method: 'POST',
			body: JSON.stringify({
				car_plate: state.carPlate,
				fuel_type_id: els.fuelSelect.value,
				plate_format_confirmed: state.plateFormatConfirmed,
			}),
		}).then(function (data) {
			renderTicket(data.ticket, data.state === 'active' || data.state === 'active_own' ? 'По этому госномеру уже есть активный QR-код.' : 'QR-код готов.');
		}).catch(function (err) {
			if (err && err.sessionExpired) {
				startAuthFlow();
				return;
			}
			showMessage(err.message, 'error');
		}).finally(function () {
			setBusy(els.createSubmit, false);
		});
	}

	function bindEvents() {
		els.retryCaptcha.addEventListener('click', function () {
			clearMessage();
			els.retryCaptcha.hidden = true;
			resetCaptcha();
			if (!window.__fuelCaptchaReady) {
				showCaptchaGate();
			}
		});
		els.plateForm.addEventListener('submit', onPlateSubmit);
		els.fuelForm.addEventListener('submit', onFuelSubmit);
		els.backToPlate.addEventListener('click', function () {
			clearMessage();
			els.fuelSelect.value = '';
			setStatus('Госномер');
			showStep('plate');
			els.plateInput.focus();
		});
		els.newRequest.addEventListener('click', function () {
			clearMessage();
			state.carPlate = '';
			state.plateFormatConfirmed = false;
			state.pendingPlateConfirmation = '';
			state.currentTicket = null;
			els.ticket.hidden = true;
			updateShareButton();
			els.plateInput.value = '';
			openForm();
		});
		els.share.addEventListener('click', function () {
			if (!isValidTicket(state.currentTicket) || !window.navigator.share) {
				return;
			}

			setBusy(els.share, true);
			window.navigator.share(shareDataForTicket(state.currentTicket)).catch(function (err) {
				if (err && err.name === 'AbortError') {
					return;
				}
				showMessage('Не удалось открыть меню отправки. Скопируйте ссылку на QR-код.', 'error');
			}).finally(function () {
				setBusy(els.share, false);
			});
		});
	}

	function init() {
		initElements();
		state.clientId = readStoredClientId() || getClientId();
		state.authMode = readAuthMode();
		bindEvents();
		updateShareButton();
		if (!state.authMode) {
			showUnsupported('Некорректный режим открытия', 'Некорректный параметр в адресе.', 'Некорректный параметр mode.');
			return;
		}
		if (shouldCheckSession()) {
			checkSessionStatus();
			return;
		}
		clearSessionMarker();
		startAuthFlow();
	}

	window.FuelQrPage = {
		onCaptchaLoad: onCaptchaLoad,
	};

	if (window.__fuelCaptchaReady) {
		onCaptchaLoad();
	}

	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', init);
	} else {
		init();
	}
}());