(function lendrySsoWidget(global) {
  'use strict';

  var MESSAGE_TYPE = 'lendry-sso-onetap';
  var DEFAULT_SCOPE = 'openid profile email';
  var widgetRootId = 'lendry-sso-onetap-root';

  function trimSlash(value) {
    return String(value || '').replace(/\/+$/, '');
  }

  function resolveScriptElement() {
    var current = global.document.currentScript;
    if (current) return current;
    var scripts = global.document.getElementsByTagName('script');
    for (var i = scripts.length - 1; i >= 0; i -= 1) {
      var src = scripts[i].getAttribute('src') || '';
      if (src.indexOf('sso-widget.js') !== -1) {
        return scripts[i];
      }
    }
    return null;
  }

  function resolveIdpApiBase(script) {
    var override = script && script.getAttribute('data-idp-url');
    if (override) return trimSlash(override);
    try {
      var origin = new URL(script.src).origin;
      return trimSlash(origin + '/idp-api');
    } catch (_error) {
      return '';
    }
  }

  function resolveFrontendBase(script, idpApiBase) {
    var override = script && script.getAttribute('data-idp-frontend-url');
    if (override) return trimSlash(override);
    try {
      return new URL(script.src).origin;
    } catch (_error) {
      if (idpApiBase.indexOf('/idp-api') !== -1) {
        return idpApiBase.replace(/\/idp-api$/, '');
      }
      return idpApiBase;
    }
  }

  function resolveProviderName(script) {
    return (script && script.getAttribute('data-provider-name')) || 'MVK ID';
  }

  function dispatchSuccess(payload, script) {
    var callbackName = script && script.getAttribute('data-on-success');
    if (callbackName && typeof global[callbackName] === 'function') {
      global[callbackName](payload);
    }
    try {
      global.dispatchEvent(new CustomEvent('lendry-sso-onetap-success', { detail: payload }));
    } catch (_error) {
      // IE fallback not required
    }
  }

  function supportsFedCM() {
    return 'IdentityCredential' in global && global.navigator && typeof global.navigator.credentials !== 'undefined';
  }

  function isBrowserReachableBaseUrl(url) {
    try {
      var parsed = new URL(url);
      var host = parsed.hostname.toLowerCase();
      if (host === 'api-gateway' || host === 'sso-core' || host === 'frontend' || host === 'docs') {
        return false;
      }
      if (host.indexOf('.') === -1 && host !== 'localhost') {
        return false;
      }
      return parsed.protocol === 'http:' || parsed.protocol === 'https:';
    } catch (_error) {
      return false;
    }
  }

  function loginWithFedCM(idpApiBase, clientId) {
    if (!supportsFedCM()) {
      return Promise.resolve(null);
    }

    function requestFedCMConfig(configUrl) {
      return global.navigator.credentials
        .get({
          identity: {
            providers: [
              {
                configURL: configUrl,
                configUrl: configUrl,
                clientId: clientId,
                fields: ['name', 'email', 'picture', 'tel']
              }
            ]
          },
          mediation: 'optional'
        })
        .then(function (credential) {
          if (!credential || typeof credential !== 'object') return null;
          var token = credential.token;
          if (!token) return null;
          return {
            token: token,
            method: 'fedcm'
          };
        });
    }

    function requestFedCM(configBase) {
      return requestFedCMConfig(configBase + '/fedcm/config.json');
    }

    return global.fetch(idpApiBase + '/fedcm/discover.json', { credentials: 'omit' })
      .then(function (response) {
        if (!response.ok) {
          return { mode: 'apiBase', value: idpApiBase };
        }
        return response.json().then(function (payload) {
          if (payload && payload.enabled === false) {
            return null;
          }
          if (payload && payload.configUrl && isBrowserReachableBaseUrl(payload.configUrl)) {
            return { mode: 'configUrl', value: payload.configUrl, webIdentityUrl: payload.webIdentityUrl };
          }
          if (payload && payload.apiBase && isBrowserReachableBaseUrl(payload.apiBase)) {
            return { mode: 'apiBase', value: trimSlash(payload.apiBase), webIdentityUrl: payload.webIdentityUrl };
          }
          if (isBrowserReachableBaseUrl(idpApiBase)) {
            return { mode: 'apiBase', value: idpApiBase };
          }
          return null;
        });
      })
      .catch(function () {
        if (isBrowserReachableBaseUrl(idpApiBase)) {
          return { mode: 'apiBase', value: idpApiBase };
        }
        return null;
      })
      .then(function (resolved) {
        if (!resolved) {
          if (global.console && typeof global.console.warn === 'function') {
            global.console.warn(
              '[MVK ID] FedCM: URL IdP недоступен из браузера. Укажите публичный data-idp-url (например https://api.idpmvk.lpr), не внутренний Docker-хост.'
            );
          }
          return null;
        }
        if (resolved.mode === 'configUrl') {
          return requestFedCMConfig(resolved.value);
        }
        return requestFedCM(resolved.value);
      })
      .catch(function (error) {
        if (global.console && typeof global.console.debug === 'function') {
          global.console.debug(
            '[MVK ID] FedCM недоступен (будет использован popup):',
            error,
            'Для One Tap без popup: примите SSL для корневого домена IdP (например idpmvk.lpr) и проверьте /.well-known/web-identity.'
          );
        }
        return null;
      });
  }

  function exchangeAuthorizationCode(idpApiBase, clientId, clientSecret, code, redirectUri) {
    if (!code || !clientId || !clientSecret) {
      return Promise.reject(new Error('Для обмена code нужны clientId, clientSecret и authorization code'));
    }
    var body = new URLSearchParams();
    body.set('grant_type', 'authorization_code');
    body.set('code', code);
    body.set('client_id', clientId);
    body.set('client_secret', clientSecret);
    body.set('redirect_uri', redirectUri);
    return global.fetch(trimSlash(idpApiBase) + '/oauth/token', {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: body.toString()
    }).then(function (response) {
      return response.json().then(function (payload) {
        if (!response.ok) {
          var message = payload && (payload.message || payload.error_description || payload.error);
          throw new Error(message || 'Не удалось обменять authorization code');
        }
        return payload;
      });
    });
  }

  var SIZE_PRESETS = {
    s: { height: 32, font: 13, padX: 12, gap: 8, badge: 20, radius: 16 },
    m: { height: 40, font: 14, padX: 16, gap: 10, badge: 24, radius: 20 },
    l: { height: 44, font: 15, padX: 18, gap: 10, badge: 28, radius: 22 },
    xl: { height: 52, font: 16, padX: 22, gap: 12, badge: 32, radius: 26 }
  };

  function themePalette(theme) {
    if (theme === 'dark') {
      return {
        bg: '#1f2430',
        bgHover: '#2a3040',
        border: 'transparent',
        borderHover: 'transparent',
        text: '#ffffff',
        badgeBg: '#ffffff',
        badgeColor: '#1f2430'
      };
    }
    return {
      bg: '#ffffff',
      bgHover: '#f6f8fb',
      border: '#e4e8ef',
      borderHover: '#d4dae6',
      text: '#1f2430',
      badgeBg: '#111111',
      badgeColor: '#ffffff'
    };
  }

  function readButtonOptions(script, options) {
    function attr(name) {
      return script ? script.getAttribute(name) : null;
    }
    var o = options || {};
    var size = String(o.buttonSize || attr('data-button-size') || 'xl').toLowerCase();
    if (!SIZE_PRESETS[size]) size = 'xl';
    var radiusRaw = o.buttonRadius != null ? o.buttonRadius : attr('data-button-radius');
    return {
      size: size,
      theme: String(o.buttonTheme || attr('data-button-theme') || 'light').toLowerCase(),
      view: String(o.buttonView || attr('data-button-view') || 'main').toLowerCase(),
      icon: String(o.buttonIcon || attr('data-button-icon') || 'id').toLowerCase(),
      radius: radiusRaw != null && radiusRaw !== '' ? parseInt(radiusRaw, 10) : null,
      container: o.buttonContainer || attr('data-button-container') || null,
      colors: {
        bg: o.buttonBg || attr('data-button-bg') || null,
        bgHover: o.buttonBgHover || attr('data-button-bg-hover') || null,
        border: o.buttonBorder || attr('data-button-border') || null,
        borderHover: o.buttonBorderHover || attr('data-button-border-hover') || null,
        text: o.buttonText || attr('data-button-text') || null
      }
    };
  }

  function injectWidgetStyles() {
    if (global.document.getElementById('lendry-sso-onetap-style')) return;
    var style = global.document.createElement('style');
    style.id = 'lendry-sso-onetap-style';
    style.textContent =
      '#' +
      widgetRootId +
      '{position:fixed;top:16px;right:16px;z-index:2147483000}' +
      '.lendry-sso-onetap-btn{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;font-weight:600;line-height:1;cursor:pointer;white-space:nowrap;transition:transform .18s ease,box-shadow .18s ease,background .18s ease,border-color .18s ease;box-shadow:0 8px 24px rgba(31,36,48,.12)}' +
      '.lendry-sso-onetap-btn:hover{transform:translateY(-1px);box-shadow:0 12px 28px rgba(31,36,48,.16)}' +
      '.lendry-sso-onetap-btn:active{transform:translateY(0)}' +
      '.lendry-sso-onetap-badge{display:inline-flex;align-items:center;justify-content:center;border-radius:999px;font-weight:700}';
    global.document.head.appendChild(style);
  }

  function applyButtonStyles(button, badge, providerName, btn) {
    var preset = SIZE_PRESETS[btn.size] || SIZE_PRESETS.xl;
    var palette = themePalette(btn.theme === 'dark' ? 'dark' : 'light');
    var bg = btn.colors.bg || palette.bg;
    var bgHover = btn.colors.bgHover || palette.bgHover;
    var border = btn.colors.border || palette.border;
    var borderHover = btn.colors.borderHover || palette.borderHover;
    var textColor = btn.colors.text || palette.text;
    var radius = btn.radius != null && !isNaN(btn.radius) ? btn.radius : preset.radius;
    var iconOnly = btn.view === 'icon';

    button.style.height = preset.height + 'px';
    button.style.fontSize = preset.font + 'px';
    button.style.gap = preset.gap + 'px';
    button.style.padding = iconOnly ? '0' : '0 ' + preset.padX + 'px';
    button.style.width = iconOnly ? preset.height + 'px' : 'auto';
    button.style.borderRadius = radius + 'px';
    button.style.background = bg;
    button.style.color = textColor;
    button.style.border = '1px solid ' + border;

    button.addEventListener('mouseenter', function () {
      button.style.background = bgHover;
      button.style.borderColor = borderHover;
    });
    button.addEventListener('mouseleave', function () {
      button.style.background = bg;
      button.style.borderColor = border;
    });

    if (badge) {
      badge.style.minWidth = preset.badge + 'px';
      badge.style.height = preset.badge + 'px';
      badge.style.padding = '0 ' + Math.round(preset.badge / 4) + 'px';
      badge.style.fontSize = Math.round(preset.font * 0.85) + 'px';
      badge.style.background = palette.badgeBg;
      badge.style.color = palette.badgeColor;
    }
  }

  function createWidget(providerName, onClick, options) {
    injectWidgetStyles();
    var btn = options || readButtonOptions(null, null);
    var iconOnly = btn.view === 'icon';

    var mount = null;
    if (btn.container) {
      mount = global.document.getElementById(btn.container);
      if (mount) {
        mount.innerHTML = '';
      }
    }
    if (!mount) {
      if (global.document.getElementById(widgetRootId)) return;
      mount = global.document.createElement('div');
      mount.id = widgetRootId;
      global.document.body.appendChild(mount);
    }

    var button = global.document.createElement('button');
    button.type = 'button';
    button.className = 'lendry-sso-onetap-btn';
    button.setAttribute('aria-label', 'Войти через ' + providerName);

    var badge = null;
    if (btn.icon !== 'none') {
      badge = global.document.createElement('span');
      badge.className = 'lendry-sso-onetap-badge';
      badge.textContent = 'ID';
      button.appendChild(badge);
    }

    if (!iconOnly) {
      var label = global.document.createElement('span');
      label.textContent = 'Войти через ' + providerName;
      button.appendChild(label);
    }

    applyButtonStyles(button, badge, providerName, btn);
    button.addEventListener('click', onClick);
    mount.appendChild(button);
  }

  function buildPopupUrl(frontendBase, clientId, origin, redirectUri, scope) {
    var params = new URLSearchParams();
    params.set('client_id', clientId);
    params.set('redirect_uri', redirectUri);
    params.set('response_type', 'code');
    params.set('scope', scope || DEFAULT_SCOPE);
    params.set('display', 'popup');
    params.set('popup_origin', origin);
    params.set('state', 'onetap_' + Math.random().toString(36).slice(2));
    return frontendBase + '/auth/oauth/authorize?' + params.toString();
  }

  function openPopup(url, expectedOrigin, onToken) {
    var width = 480;
    var height = 640;
    var left = Math.max(0, Math.round((global.screen.width - width) / 2));
    var top = Math.max(0, Math.round((global.screen.height - height) / 2));
    // Без noopener/noreferrer: popup должен видеть window.opener для postMessage после «Разрешить».
    var features =
      'popup=yes,width=' +
      width +
      ',height=' +
      height +
      ',left=' +
      left +
      ',top=' +
      top;

    var popup = global.open(url, 'lendry_sso_onetap', features);
    if (!popup) {
      if (global.console && typeof global.console.error === 'function') {
        global.console.error('[MVK ID] Не удалось открыть popup. Разрешите всплывающие окна.');
      }
      return function cleanup() {};
    }

    function handleMessage(event) {
      if (!event || !event.data || event.data.type !== MESSAGE_TYPE) return;
      if (expectedOrigin && event.origin !== expectedOrigin && event.origin !== trimSlash(expectedOrigin)) return;

      cleanup();
      onToken(event.data);
    }

    function cleanup() {
      global.removeEventListener('message', handleMessage);
      if (popup && !popup.closed) {
        try {
          popup.close();
        } catch (_error) {
          // ignore
        }
      }
    }

    global.addEventListener('message', handleMessage);
    return cleanup;
  }

  function initOneTap(options) {
    var script = resolveScriptElement();
    var clientId = (options && options.clientId) || (script && script.getAttribute('data-client-id'));
    if (!clientId) {
      if (global.console && typeof global.console.error === 'function') {
        global.console.error('[MVK ID] Укажите data-client-id в теге script или clientId в LendryIdOneTap.init().');
      }
      return;
    }

    var idpApiBase = trimSlash((options && options.idpUrl) || resolveIdpApiBase(script));
    var frontendBase = trimSlash((options && options.frontendUrl) || resolveFrontendBase(script, idpApiBase));
    var providerName = (options && options.providerName) || resolveProviderName(script);
    var scope = (options && options.scope) || (script && script.getAttribute('data-scope')) || DEFAULT_SCOPE;
    var redirectUri =
      (options && options.redirectUri) ||
      (script && script.getAttribute('data-redirect-uri')) ||
      global.location.origin + '/auth/callback';
    var buttonOptions = readButtonOptions(script, options);

    loginWithFedCM(idpApiBase, clientId).then(function (result) {
      if (result && result.token) {
        dispatchSuccess(
          {
            token: result.token,
            idToken: result.token,
            grantType: 'id_token',
            method: 'fedcm'
          },
          script
        );
        return;
      }

      createWidget(
        providerName,
        function () {
          var popupUrl = buildPopupUrl(frontendBase, clientId, global.location.origin, redirectUri, scope);
          openPopup(popupUrl, frontendBase, function (payload) {
            dispatchSuccess(
              {
                code: payload.code,
                state: payload.state,
                grantType: payload.grantType || (payload.code ? 'authorization_code' : undefined),
                idToken: payload.idToken,
                accessToken: payload.accessToken,
                refreshToken: payload.refreshToken,
                tokenEndpoint: trimSlash(idpApiBase) + '/oauth/token',
                redirectUri: redirectUri,
                method: 'popup'
              },
              script
            );
          });
        },
        buttonOptions
      );
    });
  }

  global.LendryIdOneTap = {
    init: initOneTap,
    loginWithFedCM: loginWithFedCM,
    exchangeAuthorizationCode: exchangeAuthorizationCode,
    MESSAGE_TYPE: MESSAGE_TYPE
  };

  var scriptEl = resolveScriptElement();
  if (scriptEl && scriptEl.getAttribute('data-auto-init') !== 'false') {
    if (global.document.readyState === 'loading') {
      global.document.addEventListener('DOMContentLoaded', function () {
        initOneTap();
      });
    } else {
      initOneTap();
    }
  }
})(window);
