(function(window) {
  'use strict';

  const FIDO2_UI_VERSION = '1.0.0';

  const DEFAULT_CONFIG = {
    serverUrl: 'https://fido2.amipro.me',
    mode: 'modal',
    container: null,
    theme: {
      logo: null,
      primaryColor: '#696cff',
      backgroundColor: '#ffffff',
      textColor: '#333333',
      borderRadius: '8px',
    },
    language: 'zh-CN',
    customI18n: {},
    features: {
      showAddButton: true,
      showDeleteButton: true,
      showUserInfo: true,
      showSessionStatus: true,
    },
    callbacks: {},
    rpId: null,
    autoRefresh: true,
    refreshInterval: 5000,
  };

  const DEFAULT_I18N = {
    'my_devices': {
      'en-US': 'My devices',
      'zh-CN': '我的设备',
      'ja': 'マイデバイス'
    },
    'btn_add': {
      'en-US': 'Add device',
      'zh-CN': '添加设备',
      'ja': 'デバイスを追加'
    },
    'title_device': {
      'en-US': 'Device',
      'zh-CN': '设备',
      'ja': 'デバイス'
    },
    'title_time': {
      'en-US': 'Registered time',
      'zh-CN': '添加时间',
      'ja': '登録時間'
    },
    'title_act': {
      'en-US': 'Actions',
      'zh-CN': '操作',
      'ja': '操作'
    },
    'title_del': {
      'en-US': 'Delete',
      'zh-CN': '删除',
      'ja': '削除'
    },
    'title_logout': {
      'en-US': 'Log out',
      'zh-CN': '登出',
      'ja': 'ログアウト'
    },
    'title_empty_list': {
      'en-US': 'No devices, please add.',
      'zh-CN': '无设备，请添加。',
      'ja': 'デバイスがなし、追加してください。'
    },
    'msg_register_ok': {
      'en-US': 'Device registered successfully',
      'zh-CN': '添加设备成功',
      'ja': 'デバイス登録完了'
    },
    'msg_deldev_ok': {
      'en-US': 'Device deleted successfully',
      'zh-CN': '设备删除成功',
      'ja': 'デバイスを削除しました'
    },
    'msg_confirm_deldev': {
      'en-US': 'Do you want to delete this device?',
      'zh-CN': '确认删除此设备吗？',
      'ja': 'デバイスを削除しますか？'
    },
    'msg_session_status_ok': {
      'en-US': 'FIDO2 session is valid',
      'zh-CN': 'FIDO2会话正常',
      'ja': 'FIDO2セッションは正常です'
    },
    'msg_session_status_fail': {
      'en-US': 'FIDO2 session is invalid',
      'zh-CN': 'FIDO2会话无效',
      'ja': 'FIDO2セッションは無効です'
    },
    'btn_close': {
      'en-US': 'Close',
      'zh-CN': '关闭',
      'ja': '閉じる'
    },
    'title_welcome': {
      'en-US': 'Welcome',
      'zh-CN': '欢迎',
      'ja': 'ようこそ'
    },
    'btn_login': {
      'en-US': 'Login',
      'zh-CN': '重新登录',
      'ja': 'ログイン'
    },
    'msg_session_invalid': {
      'en-US': 'Session expired, please login again',
      'zh-CN': '会话已过期，请重新登录',
      'ja': 'セッション切れ、再ログインしてください'
    }
  };

  function I18nManager(config) {
    this.config = config;
    this.messages = new Map();

    for (let key in DEFAULT_I18N) {
      this.messages.set(key, new Map());
      for (let lang in DEFAULT_I18N[key]) {
        this.messages.get(key).set(lang, DEFAULT_I18N[key][lang]);
      }
    }

    if (config.customI18n) {
      for (let key in config.customI18n) {
        if (!this.messages.has(key)) {
          this.messages.set(key, new Map());
        }
        for (let lang in config.customI18n[key]) {
          this.messages.get(key).set(lang, config.customI18n[key][lang]);
        }
      }
    }
  }

  I18nManager.prototype.getText = function(key) {
    const lang = this.config.language || window.navigator.language || 'en-US';
    const keyMap = this.messages.get(key);

    if (!keyMap) return key;

    let text = keyMap.get(lang);
    if (!text) text = keyMap.get('en-US');

    return text || key;
  };

  function EventManager() {
    this.callbacks = {};
  }

  EventManager.prototype.on = function(event, callback) {
    if (!this.callbacks[event]) {
      this.callbacks[event] = [];
    }
    this.callbacks[event].push(callback);
  };

  EventManager.prototype.off = function(event, callback) {
    if (!this.callbacks[event]) return;

    const index = this.callbacks[event].indexOf(callback);
    if (index > -1) {
      this.callbacks[event].splice(index, 1);
    }
  };

  EventManager.prototype.emit = function(event, data) {
    if (!this.callbacks[event]) return;

    this.callbacks[event].forEach(function(callback) {
      callback(data);
    });
  };

  function ThemeManager(config) {
    this.config = config;
  }

  ThemeManager.prototype.applyTheme = function(element) {
    if (!element) return;

    const theme = this.config.theme;
    const styleId = 'fido2-ui-sdk-theme-' + Date.now();

    let css = '';
    if (theme.primaryColor) {
      css += '.fido2-sdk-btn-primary { background-color: ' + theme.primaryColor + '!important; border-color: ' + theme.primaryColor + '!important; }';
      css += '.fido2-sdk-header { border-bottom: 2px solid ' + theme.primaryColor + '!important; }';
    }
    if (theme.backgroundColor) {
      css += '.fido2-sdk-container { background-color: ' + theme.backgroundColor + '!important; }';
    }
    if (theme.textColor) {
      css += '.fido2-sdk-text { color: ' + theme.textColor + '!important; }';
    }
    if (theme.borderRadius) {
      css += '.fido2-sdk-card, .fido2-sdk-btn { border-radius: ' + theme.borderRadius + '!important; }';
    }

    if (css) {
      let style = document.getElementById(styleId);
      if (style) {
        style.parentNode.removeChild(style);
      }

      style = document.createElement('style');
      style.id = styleId;
      style.textContent = css;
      document.head.appendChild(style);
    }

    element.dataset.themeStyleId = styleId;
  };

  ThemeManager.prototype.cleanup = function(element) {
    if (!element) return;

    const styleId = element.dataset.themeStyleId;
    if (styleId) {
      const style = document.getElementById(styleId);
      if (style) {
        style.parentNode.removeChild(style);
      }
    }
  };

  function DeviceManager(config, i18n, eventManager) {
    this.config = config;
    this.i18n = i18n;
    this.eventManager = eventManager;
    this.devices = [];
    this.refreshTimer = null;
    this.sessionStatus = false;
  }

  DeviceManager.prototype.loadDevices = async function() {
    try {
      const result = await listUserDevicesFido2(this.config.rpId);

      if (result.status === 'ok') {
        this.devices = result.devices || [];
        this.eventManager.emit('deviceListLoaded', this.devices);
        return this.devices;
      } else {
        throw new Error(result.errorMessage || 'Failed to load devices');
      }
    } catch (error) {
      this.eventManager.emit('error', error);
      throw error;
    }
  };

  DeviceManager.prototype.addDevice = async function(displayName) {
    try {
      const sessionData = this.getSessionData();
      if (!sessionData) {
        throw new Error('No session data available');
      }

      const userId = sessionData.uid;
      const result = await registerFido2(userId, displayName || 'Device-' + userId, this.config.rpId);

      if (result.status === 'ok') {
        await this.loadDevices();
        this.eventManager.emit('deviceAdded', result);
        return result;
      } else {
        throw new Error(result.errorMessage || 'Failed to add device');
      }
    } catch (error) {
      this.eventManager.emit('error', error);
      throw error;
    }
  };

  DeviceManager.prototype.deleteDevice = async function(deviceId) {
    try {
      const result = await delUserDeviceFido2(deviceId, this.config.rpId);

      if (result.status === 'ok') {
        await this.loadDevices();
        this.eventManager.emit('deviceDeleted', deviceId);
        return result;
      } else {
        throw new Error(result.errorMessage || 'Failed to delete device');
      }
    } catch (error) {
      this.eventManager.emit('error', error);
      throw error;
    }
  };

  DeviceManager.prototype.getSessionData = function() {
    try {
      const sessionText = sessionStorage.getItem('fido2_user_session');
      if (!sessionText) return null;

      return JSON.parse(sessionText);
    } catch (error) {
      return null;
    }
  };

  DeviceManager.prototype.getUserId = function() {
    const sessionData = this.getSessionData();
    return sessionData ? sessionData.uid : null;
  };

  DeviceManager.prototype.checkSession = async function() {
    try {
      this.sessionStatus = await validSession(this.config.rpId);
      this.eventManager.emit('sessionStatusChanged', this.sessionStatus);
      return this.sessionStatus;
    } catch (error) {
      this.sessionStatus = false;
      this.eventManager.emit('sessionStatusChanged', false);
      return false;
    }
  };

  DeviceManager.prototype.parseDeviceDescription = function(device) {
    if (device.desc && device.desc.length > 0) {
      return device.desc;
    }

    try {
      if (device.userAgent && typeof UAParser !== 'undefined') {
        const parser = new UAParser(device.userAgent);
        if (parser.getOS().name) {
          return parser.getDevice().model + ',' + parser.getOS().name + ',' + parser.getBrowser().name;
        }
      }
      return device.userAgent || 'Unknown Device';
    } catch (error) {
      return 'Unknown Device';
    }
  };

  DeviceManager.prototype.startAutoRefresh = function() {
    if (!this.config.autoRefresh) return;

    this.stopAutoRefresh();

    this.refreshTimer = setInterval(async () => {
      try {
        await this.loadDevices();
        await this.checkSession();
      } catch (error) {
        console.error('Auto refresh error:', error);
      }
    }, this.config.refreshInterval);
  };

  DeviceManager.prototype.stopAutoRefresh = function() {
    if (this.refreshTimer) {
      clearInterval(this.refreshTimer);
      this.refreshTimer = null;
    }
  };

  function UIRenderer(config, i18n, themeManager, eventManager) {
    this.config = config;
    this.i18n = i18n;
    this.themeManager = themeManager;
    this.eventManager = eventManager;
    this.modalElement = null;
    this.containerElement = null;
  }

  UIRenderer.prototype.renderModal = function() {
    if (!this.config.container) {
      throw new Error('Container is required for modal mode');
    }

    const container = typeof this.config.container === 'string'
      ? document.querySelector(this.config.container)
      : this.config.container;

    if (!container) {
      throw new Error('Container not found: ' + this.config.container);
    }

    container.innerHTML = '';

    const modal = document.createElement('div');
    modal.className = 'modal fade fido2-sdk-modal';
    modal.id = 'fido2SdkModal';
    modal.tabIndex = -1;
    modal.setAttribute('aria-hidden', 'true');

    modal.innerHTML = this._getModalHTML();
    container.appendChild(modal);
    this.modalElement = modal;
    this.containerElement = container;

    this.themeManager.applyTheme(modal);

    const bootstrapModal = new window.bootstrap.Modal(modal, {
      backdrop: true,
      keyboard: true
    });

    bootstrapModal.show();

    modal.addEventListener('hidden.bs.modal', () => {
      this.eventManager.emit('close');
      this.cleanup();
    });

    this._bindEvents();

    return modal;
  };

  UIRenderer.prototype._getModalHTML = function() {
    const theme = this.config.theme;

    return `
      <div class="modal-dialog modal-dialog-centered modal-lg">
        <div class="modal-content fido2-sdk-card">
          <div class="modal-header fido2-sdk-header">
            ${theme.logo ? `<img src="${theme.logo}" class="fido2-sdk-logo" alt="Logo">` : ''}
            <h5 class="modal-title fido2-sdk-text">${this.i18n.getText('my_devices')}</h5>
            ${this.config.features.showSessionStatus ? '<span class="badge fido2-sdk-status-badge" id="fido2SessionStatus"></span>' : ''}
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body fido2-sdk-container">
            ${this._getBodyHTML()}
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary fido2-sdk-btn" data-bs-dismiss="modal">${this.i18n.getText('btn_close')}</button>
          </div>
        </div>
      </div>
    `;
  };

  UIRenderer.prototype._getBodyHTML = function() {
    const features = this.config.features;
    const userId = window.Fido2UIManager.deviceManager ? window.Fido2UIManager.deviceManager.getUserId() : '';

    let html = '';

    if (features.showUserInfo && userId) {
      html += `<div class="fido2-sdk-user-info mb-3 fido2-sdk-text">
        <strong>${this.i18n.getText('title_welcome')}:</strong> ${userId}
      </div>`;
    }

    html += `<div id="fido2SessionAlert" class="alert alert-warning mb-3 fido2-sdk-text" style="display:none;">
      ${this.i18n.getText('msg_session_invalid')}
      <button type="button" class="btn btn-sm btn-primary ms-2" id="fido2LoginBtn">
        ${this.i18n.getText('btn_login')}
      </button>
    </div>`;

    if (features.showAddButton) {
      html += `
        <button type="button" class="btn btn-info mb-3 fido2-sdk-btn fido2-sdk-btn-primary" id="fido2AddDeviceBtn">
          ${this.i18n.getText('btn_add')}
        </button>
      `;
    }

    html += `
      <div class="table-responsive">
        <table class="table table-striped fido2-sdk-table">
          <thead>
            <tr>
              <th>${this.i18n.getText('title_device')}</th>
              <th>${this.i18n.getText('title_time')}</th>
              ${features.showDeleteButton ? `<th>${this.i18n.getText('title_act')}</th>` : ''}
            </tr>
          </thead>
          <tbody id="fido2DevicesList">
            <tr>
              <td colspan="3" class="text-center fido2-sdk-text">${this.i18n.getText('title_empty_list')}</td>
            </tr>
          </tbody>
        </table>
      </div>
    `;

    return html;
  };

  UIRenderer.prototype._bindEvents = function() {
    const container = this.modalElement || this.containerElement;
    if (!container) return;

    container.querySelectorAll('[data-fido2-action="delete"]').forEach(btn => {
      btn.replaceWith(btn.cloneNode(true));
    });

    const addBtn = container.querySelector('#fido2AddDeviceBtn');
    if (addBtn) {
      addBtn.replaceWith(addBtn.cloneNode(true));
      const newAddBtn = container.querySelector('#fido2AddDeviceBtn');
      newAddBtn.addEventListener('click', () => {
        this.eventManager.emit('addDevice');
      });
    }

    const loginBtn = container.querySelector('#fido2LoginBtn');
    if (loginBtn) {
      loginBtn.replaceWith(loginBtn.cloneNode(true));
      const newLoginBtn = container.querySelector('#fido2LoginBtn');
      newLoginBtn.addEventListener('click', () => {
        this.eventManager.emit('login');
      });
    }

    container.querySelectorAll('[data-fido2-action="delete"]').forEach(btn => {
      btn.addEventListener('click', (e) => {
        e.preventDefault();
        const deviceId = btn.dataset.deviceId;
        if (deviceId && confirm(this.i18n.getText('msg_confirm_deldev'))) {
          this.eventManager.emit('deleteDevice', deviceId);
        }
      });
    });
  };

  UIRenderer.prototype.updateDevicesList = function(devices) {
    const tbody = document.getElementById('fido2DevicesList');
    if (!tbody) return;

    if (!devices || devices.length === 0) {
      tbody.innerHTML = `
        <tr>
          <td colspan="3" class="text-center fido2-sdk-text">${this.i18n.getText('title_empty_list')}</td>
        </tr>
      `;
      return;
    }

    let html = '';
    const dm = window.Fido2UIManager ? window.Fido2UIManager.deviceManager : null;

    devices.forEach(device => {
      const desc = dm ? dm.parseDeviceDescription(device) : device.desc || 'Unknown Device';
      const date = new Date(device.registered_time).toLocaleString();

      html += `
        <tr>
          <td class="fido2-sdk-text"><strong>${desc}</strong></td>
          <td class="fido2-sdk-text">${date}</td>
          ${this.config.features.showDeleteButton ? `
            <td>
              <a href="javascript:void(0)" 
                 class="text-danger" 
                 data-fido2-action="delete" 
                 data-device-id="${device.device_id}">
                <i class="bx bx-trash"></i> ${this.i18n.getText('title_del')}
              </a>
            </td>
          ` : ''}
        </tr>
      `;
    });

    tbody.innerHTML = html;
    this._bindEvents();
  };

  UIRenderer.prototype.updateSessionStatus = function(isValid) {
    const badge = document.getElementById('fido2SessionStatus');
    const alertDiv = document.getElementById('fido2SessionAlert');
    const addBtn = document.getElementById('fido2AddDeviceBtn');

    if (badge) {
      if (isValid) {
        badge.className = 'badge bg-success fido2-sdk-status-badge';
        badge.textContent = this.i18n.getText('msg_session_status_ok');
      } else {
        badge.className = 'badge bg-danger fido2-sdk-status-badge';
        badge.textContent = this.i18n.getText('msg_session_status_fail');
      }
    }

    if (alertDiv) {
      alertDiv.style.display = isValid ? 'none' : 'block';
    }

    if (addBtn) {
      addBtn.disabled = !isValid;
    }
  };

  UIRenderer.prototype.close = function() {
    if (this.modalElement) {
      const bootstrapModal = window.bootstrap.Modal.getInstance(this.modalElement);
      if (bootstrapModal) {
        bootstrapModal.hide();
      }
    }
  };

  UIRenderer.prototype.cleanup = function() {
    if (this.modalElement) {
      this.themeManager.cleanup(this.modalElement);
      if (this.modalElement.parentNode) {
        this.modalElement.parentNode.removeChild(this.modalElement);
      }
      this.modalElement = null;
    }
    this.containerElement = null;
  };

  UIRenderer.prototype.renderStandalone = function() {
    if (this.config.container) {
      const container = typeof this.config.container === 'string'
        ? document.querySelector(this.config.container)
        : this.config.container;

      if (container) {
        container.innerHTML = this._getStandaloneBodyHTML();
        this.containerElement = container;
        this.themeManager.applyTheme(container);
        this._bindEvents();
        return container;
      }
    }

    document.body.innerHTML = this._getStandaloneBodyHTML();
    document.body.className = 'fido2-sdk-standalone';
    this.containerElement = document.body;
    this.themeManager.applyTheme(document.body);
    this._bindEvents();
    return document.body;
  };

  UIRenderer.prototype._getStandaloneBodyHTML = function() {
    const theme = this.config.theme;
    const userId = window.Fido2UIManager.deviceManager ? window.Fido2UIManager.deviceManager.getUserId() : '';

    return `
      <div class="container fido2-sdk-container">
        <div class="card fido2-sdk-card">
          <div class="card-header fido2-sdk-header d-flex justify-content-between align-items-center">
            <div>
              ${theme.logo ? `<img src="${theme.logo}" class="fido2-sdk-logo me-2" alt="Logo">` : ''}
              <h4 class="mb-0 fido2-sdk-text">${this.i18n.getText('my_devices')}</h4>
            </div>
            ${this.config.features.showSessionStatus ? '<span class="badge fido2-sdk-status-badge" id="fido2SessionStatus"></span>' : ''}
          </div>
          <div class="card-body fido2-sdk-body">
            ${this.config.features.showUserInfo && userId ? `
              <div class="alert alert-info fido2-sdk-user-info fido2-sdk-text">
                <strong>${this.i18n.getText('title_welcome')}:</strong> ${userId}
              </div>
            ` : ''}
            <div id="fido2SessionAlert" class="alert alert-warning mb-3 fido2-sdk-text" style="display:none;">
              ${this.i18n.getText('msg_session_invalid')}
              <button type="button" class="btn btn-sm btn-primary ms-2" id="fido2LoginBtn">
                ${this.i18n.getText('btn_login')}
              </button>
            </div>
            ${this.config.features.showAddButton ? `
              <button type="button" class="btn btn-info mt-2 mb-3 fido2-sdk-btn fido2-sdk-btn-primary" id="fido2AddDeviceBtn">
                ${this.i18n.getText('btn_add')}
              </button>
            ` : ''}
            <div class="table-responsive mt-2">
              <table class="table table-striped fido2-sdk-table">
                <thead>
                  <tr>
                    <th>${this.i18n.getText('title_device')}</th>
                    <th>${this.i18n.getText('title_time')}</th>
                    ${this.config.features.showDeleteButton ? `<th>${this.i18n.getText('title_act')}</th>` : ''}
                  </tr>
                </thead>
                <tbody id="fido2DevicesList">
                  <tr>
                    <td colspan="3" class="text-center fido2-sdk-text">${this.i18n.getText('title_empty_list')}</td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </div>
    `;
  };

  UIRenderer.prototype._getStandaloneHTML = function() {
    const theme = this.config.theme;
    const userId = window.Fido2UIManager.deviceManager ? window.Fido2UIManager.deviceManager.getUserId() : '';

    return `
      <!DOCTYPE html>
      <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>${this.i18n.getText('my_devices')}</title>
        <link rel="stylesheet" href="files/bootstrap.css">
        <link rel="stylesheet" href="files/boxicons.css">
        <link rel="stylesheet" href="files/fido2-ui-sdk.css">
      </head>
      <body class="fido2-sdk-standalone">
        <div class="container fido2-sdk-container">
          <div class="card fido2-sdk-card">
            <div class="card-header fido2-sdk-header d-flex justify-content-between align-items-center">
              <div>
                ${theme.logo ? `<img src="${theme.logo}" class="fido2-sdk-logo me-2" alt="Logo">` : ''}
                <h4 class="mb-0 fido2-sdk-text">${this.i18n.getText('my_devices')}</h4>
              </div>
              ${this.config.features.showSessionStatus ? '<span class="badge fido2-sdk-status-badge" id="fido2SessionStatus"></span>' : ''}
            </div>
            <div class="card-body fido2-sdk-body">
              ${this.config.features.showUserInfo && userId ? `
                <div class="alert alert-info fido2-sdk-user-info fido2-sdk-text">
                  <strong>${this.i18n.getText('title_welcome')}:</strong> ${userId}
                </div>
              ` : ''}
            ${this.config.features.showAddButton ? `
              <button type="button" class="btn btn-info mt-2 mb-3 fido2-sdk-btn fido2-sdk-btn-primary" id="fido2AddDeviceBtn">
                ${this.i18n.getText('btn_add')}
              </button>
            ` : ''}
            <div class="table-responsive mt-2">
                <table class="table table-striped fido2-sdk-table">
                  <thead>
                    <tr>
                      <th>${this.i18n.getText('title_device')}</th>
                      <th>${this.i18n.getText('title_time')}</th>
                      ${this.config.features.showDeleteButton ? `<th>${this.i18n.getText('title_act')}</th>` : ''}
                    </tr>
                  </thead>
                  <tbody id="fido2DevicesList">
                    <tr>
                      <td colspan="3" class="text-center fido2-sdk-text">${this.i18n.getText('title_empty_list')}</td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        </div>
      </body>
      </html>
    `;
  };

  function Fido2UIManager() {
    this.config = null;
    this.i18n = null;
    this.eventManager = null;
    this.themeManager = null;
    this.deviceManager = null;
    this.uiRenderer = null;
    this.initialized = false;
  }

  Fido2UIManager.prototype.init = function(userConfig) {
    if (this.initialized) {
      console.warn('Fido2UIManager already initialized');
      return this;
    }

    if (!window.jQuery) {
      throw new Error('jQuery is required. Please include jQuery before fido2-ui-sdk.js');
    }

    if (!window.bootstrap) {
      throw new Error('Bootstrap is required. Please include Bootstrap JS before fido2-ui-sdk.js');
    }

    this.config = Object.assign({}, DEFAULT_CONFIG, userConfig);
    this.i18n = new I18nManager(this.config);
    this.eventManager = new EventManager();
    this.themeManager = new ThemeManager(this.config);
    this.deviceManager = new DeviceManager(this.config, this.i18n, this.eventManager);
    this.uiRenderer = new UIRenderer(this.config, this.i18n, this.themeManager, this.eventManager);

    if (this.config.serverUrl) {
      setFidoServerURL(this.config.serverUrl);
    }

    this._setupCallbacks();
    this.initialized = true;

    return this;
  };

  Fido2UIManager.prototype._setupCallbacks = function() {
    const callbacks = this.config.callbacks;

    if (callbacks.onInit) {
      this.eventManager.on('init', callbacks.onInit);
    }
    if (callbacks.onDeviceAdded) {
      this.eventManager.on('deviceAdded', callbacks.onDeviceAdded);
    }
    if (callbacks.onDeviceDeleted) {
      this.eventManager.on('deviceDeleted', callbacks.onDeviceDeleted);
    }
    if (callbacks.onDeviceListLoaded) {
      this.eventManager.on('deviceListLoaded', callbacks.onDeviceListLoaded);
    }
    if (callbacks.onError) {
      this.eventManager.on('error', callbacks.onError);
    }
    if (callbacks.onClose) {
      this.eventManager.on('close', callbacks.onClose);
    }
  };

  Fido2UIManager.prototype.renderDeviceManager = function(config) {
    const manager = new Fido2UIManager();
    manager.init(config);

    const mode = manager.config.mode;

    if (mode === 'standalone') {
      manager.uiRenderer.renderStandalone();
    } else {
      manager.uiRenderer.renderModal();
    }

    manager._bindInternalEvents();
    manager._loadInitialData();
    manager.deviceManager.startAutoRefresh();

    manager.eventManager.emit('init', manager);

    window.Fido2UIManager = manager;

    return manager;
  };

  Fido2UIManager.prototype._bindInternalEvents = function() {
    const self = this;

    this.eventManager.on('addDevice', async () => {
      const addBtn = document.getElementById('fido2AddDeviceBtn');
      if (addBtn) addBtn.disabled = true;
      try {
        const isValid = await self.deviceManager.checkSession();
        if (!isValid) {
          alert(self.i18n.getText('msg_session_status_fail') + ' ' + self.i18n.getText('btn_login'));
          return;
        }
        await self.deviceManager.addDevice();
        self.uiRenderer.updateDevicesList(self.deviceManager.devices);
        await self.deviceManager.checkSession();
        alert(self.i18n.getText('msg_register_ok'));
      } catch (error) {
        console.error('Add device error:', error);
        alert(error.message || self.i18n.getText('error'));
      } finally {
        if (addBtn) addBtn.disabled = false;
      }
    });

    this.eventManager.on('deleteDevice', async (deviceId) => {
      try {
        const isValid = await self.deviceManager.checkSession();
        if (!isValid) {
          alert(self.i18n.getText('msg_session_status_fail') + ' ' + self.i18n.getText('btn_login'));
          return;
        }
        await self.deviceManager.deleteDevice(deviceId);
        self.uiRenderer.updateDevicesList(self.deviceManager.devices);
        await self.deviceManager.checkSession();
        alert(self.i18n.getText('msg_deldev_ok'));
      } catch (error) {
        console.error('Delete device error:', error);
        alert(error.message || self.i18n.getText('error'));
      }
    });

    this.eventManager.on('login', async () => {
      try {
        const result = await authenticateFido2(null, self.config.rpId);
        if (result.status === 'ok') {
          await self.deviceManager.loadDevices();
          await self.deviceManager.checkSession();
          self.uiRenderer.updateDevicesList(self.deviceManager.devices);
        } else {
          alert(result.errorMessage || 'Login failed');
        }
      } catch (error) {
        console.error('Login error:', error);
        alert(error.message || 'Login failed');
      }
    });

    this.eventManager.on('deviceListLoaded', (devices) => {
      self.uiRenderer.updateDevicesList(devices);
    });

    this.eventManager.on('sessionStatusChanged', (isValid) => {
      self.uiRenderer.updateSessionStatus(isValid);
    });

    this.eventManager.on('error', (error) => {
      console.error('FIDO2 SDK Error:', error);
    });
  };

  Fido2UIManager.prototype._loadInitialData = async function() {
    try {
      await this.deviceManager.loadDevices();
      await this.deviceManager.checkSession();
    } catch (error) {
      console.error('Initial data load error:', error);
    }
  };

  Fido2UIManager.prototype.close = function() {
    if (this.uiRenderer) {
      this.uiRenderer.close();
    }
  };

  Fido2UIManager.prototype.refresh = async function() {
    if (this.deviceManager) {
      await this.deviceManager.loadDevices();
      await this.deviceManager.checkSession();
    }
  };

  Fido2UIManager.prototype.destroy = function() {
    if (this.deviceManager) {
      this.deviceManager.stopAutoRefresh();
    }

    if (this.uiRenderer) {
      this.uiRenderer.cleanup();
    }

    this.initialized = false;
  };

  window.Fido2UIManager = new Fido2UIManager();
  window.Fido2UIManager.renderDeviceManager = Fido2UIManager.prototype.renderDeviceManager;
  window.Fido2UIManager.close = function() {
    if (window.Fido2UIManager && window.Fido2UIManager.close) {
      window.Fido2UIManager.close();
    }
  };
  window.Fido2UIManager.refresh = function() {
    if (window.Fido2UIManager && window.Fido2UIManager.refresh) {
      window.Fido2UIManager.refresh();
    }
  };
  window.Fido2UIManager.destroy = function() {
    if (window.Fido2UIManager && window.Fido2UIManager.destroy) {
      window.Fido2UIManager.destroy();
    }
  };

  console.log('FIDO2 UI SDK v' + FIDO2_UI_VERSION + ' loaded');
})(window);
