/**
 * @file apxauthrefactor.js
 * @description Refactored WCO component for user authentication and identity management.
 * @version 2.0
 */

((window) => {
  'use strict';

  // --- Component Definition ---
  const apxauth = {};

  // --- Private State & Configuration ---
  const _state = {
    container: null, // The main DOM element for this component
    config: {},      // Initial configuration
    templates: {},   // To cache loaded Mustache templates
    currentUser: {
      alias: 'anonymous',
      profils: ['anonymous'],
      // ... other user data
    },
    headers: { // To be sent with API requests
      xalias: 'anonymous',
      xdays: null,
      xhash: null,
      xprofils: ['anonymous'],
      xtribe: null,
    }
  };

  // --- Private Helper Modules ---

  /**
   * Logger utility for consistent console output.
   */
  const _log = (level, ...args) => {
    console[level]('[apxauth]', ...args);
  };

  /**
   * Handles all interactions with the backend API.
   */
  const _api = {
    /**
     * Generic method to perform an API request.
     * @param {string} method - 'get', 'post', 'put', etc.
     * @param {string} endpoint - The API endpoint URL.
     * @param {object} [data=null] - The request payload for POST/PUT.
     * @returns {Promise<object>} - The response data.
     */
    async request(method, endpoint, data = null) {
      try {
        const options = {
          method: method.toUpperCase(),
          headers: { ..._state.headers, 'Content-Type': 'application/json' },
        };
        if (data) {
          options.body = JSON.stringify(data);
        }
        const response = await fetch(endpoint, options);
        const responseData = await response.json();
        if (!response.ok) {
          _log('error', `API Error on ${endpoint}:`, responseData);
          throw responseData; // Throw error object from backend
        }
        return responseData;
      } catch (error) {
        _log('error', `Request failed for ${endpoint}:`, error);
        throw error; // Re-throw to be caught by the caller
      }
    },

    getAliasInfo: (alias) => _api.request('get', `/api/apxtri/pagans/alias/${alias}`),
    checkAuth: () => _api.request('get', '/api/apxtri/pagans/isauth'),
    logout: () => _api.request('get', '/api/apxtri/pagans/logout'),
    recoverKey: (data) => _api.request('post', '/api/apxtri/pagans/keyrecovery', data),
    registerIdentity: (data) => _api.request('post', '/api/apxtri/pagans', data),
    joinTribe: (tribe, data) => _api.request('put', `/api/apxtri/pagans/person/${tribe}`, data),
  };

  /**
   * Encapsulates all OpenPGP-related functions.
   */
  const _pgp = {
    async generateKey(alias, passphrase) {
      return openpgp.generateKey({
        type: 'ecc',
        curve: 'curve25519',
        userIDs: [{ alias }],
        passphrase,
        format: 'armored',
      });
    },

    async createClearSignature(privateKeyArmored, passphrase, message) {
      const privateKey = await openpgp.decryptKey({
        privateKey: await openpgp.readPrivateKey({ armoredKey: privateKeyArmored }),
        passphrase,
      });
      const cleartextMessage = await openpgp.sign({
        message: await openpgp.createCleartextMessage({ text: message }),
        signingKeys: privateKey,
      });
      return btoa(cleartextMessage); // Base64 encode for transport
    }
  };

  /**
   * Handles rendering of Mustache templates.
   */
  const _render = {
    /**
     * Renders a screen template into a specific area of the component.
     * @param {string} screenName - The name of the screen to render (e.g., 'signin', 'logout').
     * @param {object} [data={}] - Additional data to pass to the template.
     */
    async screen(screenName, data = {}) {
      const target = _state.container.querySelector('.screenaction');
      if (!target) {
        _log('error', 'Render target ".screenaction" not found.');
        return;
      }
      const templateName = `apxauthscreen${screenName}`;
      if (!_state.templates[templateName]) {
        _log('error', `Template ${templateName} not found or loaded.`);
        return;
      }
      const renderData = { ..._state.currentUser, ..._state.config, ...data };
      target.innerHTML = Mustache.render(_state.templates[templateName], renderData);
      _log('log', `Rendered screen: ${screenName}`);
    },
    
    /**
     * Displays a notification message.
     * @param {string} message - The message to display.
     * @param {'success'|'error'|'info'} type - The type of message.
     */
    notification(message, type = 'error') {
        const target = _state.container.querySelector('.msginfo');
        if(target) {
            target.innerHTML = `<div class="notification ${type}">${message}</div>`;
        }
    }
  };
  
  // --- Public API & Business Logic ---

  /**
   * Sets the authentication headers required for API calls.
   * @private
   */
  async function _setAuthHeaders(alias, publicKey, privateKey, passphrase) {
    _state.headers.xalias = alias;
    _state.headers.xdays = dayjs().valueOf();
    const message = `${alias}_${_state.headers.xdays}`;
    try {
      _state.headers.xhash = await _pgp.createClearSignature(privateKey, passphrase, message);
      return true;
    } catch (error) {
      _log('error', 'Failed to create signature:', error);
      _render.notification('Could not create a valid signature. Is the passphrase correct?', 'error');
      return false;
    }
  }

  /**
   * Main authentication flow.
   */
  apxauth.login = async (alias, passphrase, privateKey) => {
    try {
      const { data: { publickey } } = await _api.getAliasInfo(alias);
      
      const headersSet = await _setAuthHeaders(alias, publickey, privateKey, passphrase);
      if (!headersSet) return;

      const { data: authData } = await _api.checkAuth();
      
      // Successfully authenticated
      _state.currentUser.alias = alias;
      _state.currentUser.profils = authData.xprofils;
      _state.headers.xprofils = authData.xprofils;
      
      _log('log', 'Authentication successful. User:', _state.currentUser);
      
      // TODO: Redirect or render the 'logout' or 'mytribes' screen
      _render.screen('logout'); // Example: render logout screen

    } catch (error) {
      _log('error', 'Login failed:', error);
      _render.notification(error.msg || 'Login failed. Please check credentials.', 'error');
    }
  };

  /**
   * Initializes the component.
   * @param {object} config - The component configuration.
   * @param {string} config.containerId - The ID of the DOM element to render into.
   * @param {object} config.templates - An object containing the pre-loaded Mustache templates.
   * @param {object} [config.initialData={}] - Any initial data to populate state.
   */
  apxauth.init = (config) => {
    _state.container = document.getElementById(config.containerId);
    if (!_state.container) {
      _log('error', `Container with ID "${config.containerId}" not found.`);
      return;
    }

    _state.config = config.initialData || {};
    _state.templates = config.templates || {};
    
    // Render the main component layout
    _state.container.innerHTML = Mustache.render(_state.templates.apxauthmain, _state.config);
    
    // Render the initial screen (e.g., 'signin' or 'logout' based on auth status)
    // For now, we default to 'signin'
    _render.screen('signin');

    // TODO: Add event listeners using event delegation
    // _state.container.addEventListener('click', _handleEvents);

    _log('log', 'apxauth component initialized.');
  };

  // Expose the component to the global window object
  window.apxauth = apxauth;

})(window);
