"use strict";

/**
 * Authentication Methods Mixin
 * 
 * Public key authentication using ECDSA signatures.
 * No passwords required - authentication is done via challenge-response.
 */

import { OxyAuthenticationError } from '../OxyServices.errors';
export function OxyServicesAuthMixin(Base) {
  return class extends Base {
    constructor(...args) {
      super(...args);
    }

    /**
     * Register a new identity with public key authentication
     * Identity is purely cryptographic - username and profile data are optional
     * 
     * @param publicKey - The user's ECDSA public key (hex)
     * @param signature - Signature of the registration request
     * @param timestamp - Timestamp when the signature was created
     */
    async register(publicKey, signature, timestamp) {
      try {
        const res = await this.makeRequest('POST', '/api/auth/register', {
          publicKey,
          signature,
          timestamp
        }, {
          cache: false
        });
        if (!res || typeof res === 'object' && Object.keys(res).length === 0) {
          throw new OxyAuthenticationError('Registration failed', 'REGISTER_FAILED', 400);
        }
        return res;
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Request an authentication challenge
     * The client must sign this challenge with their private key
     * 
     * @param publicKey - The user's public key
     */
    async requestChallenge(publicKey) {
      try {
        return await this.makeRequest('POST', '/api/auth/challenge', {
          publicKey
        }, {
          cache: false
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Verify a signed challenge and create a session
     * 
     * @param publicKey - The user's public key
     * @param challenge - The challenge string from requestChallenge
     * @param signature - Signature of the auth message
     * @param timestamp - Timestamp when the signature was created
     * @param deviceName - Optional device name
     * @param deviceFingerprint - Optional device fingerprint
     */
    async verifyChallenge(publicKey, challenge, signature, timestamp, deviceName, deviceFingerprint) {
      try {
        return await this.makeRequest('POST', '/api/auth/verify', {
          publicKey,
          challenge,
          signature,
          timestamp,
          deviceName,
          deviceFingerprint
        }, {
          cache: false
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Check if a public key is already registered
     */
    async checkPublicKeyRegistered(publicKey) {
      try {
        return await this.makeRequest('GET', `/api/auth/check-publickey/${encodeURIComponent(publicKey)}`, undefined, {
          cache: false
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Get user by public key
     */
    async getUserByPublicKey(publicKey) {
      try {
        return await this.makeRequest('GET', `/api/auth/user/${encodeURIComponent(publicKey)}`, undefined, {
          cache: true,
          cacheTTL: 2 * 60 * 1000
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Get user by session ID
     */
    async getUserBySession(sessionId) {
      try {
        return await this.makeRequest('GET', `/api/session/user/${sessionId}`, undefined, {
          cache: true,
          cacheTTL: 2 * 60 * 1000
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Batch get multiple user profiles by session IDs
     */
    async getUsersBySessions(sessionIds) {
      try {
        if (!Array.isArray(sessionIds) || sessionIds.length === 0) {
          return [];
        }
        const uniqueSessionIds = Array.from(new Set(sessionIds)).sort();
        return await this.makeRequest('POST', '/api/session/users/batch', {
          sessionIds: uniqueSessionIds
        }, {
          cache: true,
          cacheTTL: 2 * 60 * 1000,
          deduplicate: true
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Get access token by session ID
     */
    async getTokenBySession(sessionId) {
      try {
        const res = await this.makeRequest('GET', `/api/session/token/${sessionId}`, undefined, {
          cache: false,
          retry: false
        });
        this.setTokens(res.accessToken);
        return res;
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Get sessions by session ID
     */
    async getSessionsBySessionId(sessionId) {
      try {
        return await this.makeRequest('GET', `/api/session/sessions/${sessionId}`, undefined, {
          cache: false
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Logout from a specific session
     */
    async logoutSession(sessionId, targetSessionId) {
      try {
        const url = targetSessionId ? `/api/session/logout/${sessionId}/${targetSessionId}` : `/api/session/logout/${sessionId}`;
        await this.makeRequest('POST', url, undefined, {
          cache: false
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Logout from all sessions
     */
    async logoutAllSessions(sessionId) {
      try {
        await this.makeRequest('POST', `/api/session/logout-all/${sessionId}`, undefined, {
          cache: false
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Validate session
     */
    async validateSession(sessionId, options = {}) {
      try {
        const urlParams = {};
        if (options.deviceFingerprint) urlParams.deviceFingerprint = options.deviceFingerprint;
        if (options.useHeaderValidation) urlParams.useHeaderValidation = 'true';
        return await this.makeRequest('GET', `/api/session/validate/${sessionId}`, urlParams, {
          cache: false
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Check username availability
     */
    async checkUsernameAvailability(username) {
      try {
        return await this.makeRequest('GET', `/api/auth/check-username/${username}`, undefined, {
          cache: false
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    /**
     * Check email availability
     */
    async checkEmailAvailability(email) {
      try {
        return await this.makeRequest('GET', `/api/auth/check-email/${email}`, undefined, {
          cache: false
        });
      } catch (error) {
        throw this.handleError(error);
      }
    }

    // ==========================================
    // Deprecated methods - kept for reference
    // ==========================================

    /**
     * @deprecated Use register() with public key authentication instead
     */
    async signUp(username, email, password) {
      throw new OxyAuthenticationError('Password-based signup is no longer supported. Use register() with public key.', 'DEPRECATED', 410);
    }

    /**
     * @deprecated Use requestChallenge() and verifyChallenge() instead
     */
    async signIn(username, password, deviceName, deviceFingerprint) {
      throw new OxyAuthenticationError('Password-based login is no longer supported. Use challenge-response authentication.', 'DEPRECATED', 410);
    }
  };
}
//# sourceMappingURL=OxyServices.auth.js.map