// src/core/UserSessionManager.ts
import { EventEmitter } from 'events';

export interface ARUser {
  userId: string;
  deviceId: string;
  position: { x: number; y: number; z: number };
  rotation: { x: number; y: number; z: number };
  lastUpdate: number;
  isActive: boolean;
}

export interface UserSessionOptions {
  serverUrl?: string;
  heartbeatInterval?: number;
  inactivityTimeout?: number;
}

export class UserSessionManager extends EventEmitter {
  private options: UserSessionOptions;
  private users: Map<string, ARUser>;
  private currentUser: ARUser | null = null;
  private heartbeatInterval: NodeJS.Timeout | null = null;

  constructor(options: UserSessionOptions = {}) {
    super();
    this.options = {
      serverUrl: options.serverUrl || 'https://ar-session-service.example.com',
      heartbeatInterval: options.heartbeatInterval || 1000,
      inactivityTimeout: options.inactivityTimeout || 5000,
    };
    this.users = new Map();
  }

  /**
   * Initializes a user session
   */
  public async initializeSession(deviceId: string): Promise<ARUser> {
    try {
      const userId = `user-${Math.random().toString(36).substr(2, 9)}`;
      this.currentUser = {
        userId,
        deviceId,
        position: { x: 0, y: 0, z: 0 },
        rotation: { x: 0, y: 0, z: 0 },
        lastUpdate: Date.now(),
        isActive: true,
      };

      this.users.set(userId, this.currentUser);
      this.emit('userJoined', this.currentUser);
      this.startHeartbeat();

      return this.currentUser;
    } catch (error) {
      this.emit('error', error);
      throw error;
    }
  }

  /**
   * Updates the current user's position and rotation
   */
  public updateUserPosition(position: { x: number; y: number; z: number }, rotation: { x: number; y: number; z: number }): void {
    if (!this.currentUser) {
      throw new Error('No active user session');
    }

    this.currentUser.position = position;
    this.currentUser.rotation = rotation;
    this.currentUser.lastUpdate = Date.now();

    this.users.set(this.currentUser.userId, this.currentUser);
    this.emit('userUpdated', this.currentUser);
  }

  /**
   * Handles incoming user updates from other devices
   */
  public handleRemoteUserUpdate(user: ARUser): void {
    if (user.userId === this.currentUser?.userId) return;

    const existingUser = this.users.get(user.userId);
    if (existingUser) {
      Object.assign(existingUser, user);
    } else {
      this.users.set(user.userId, user);
      this.emit('userJoined', user);
    }

    this.emit('userUpdated', user);
  }

  /**
   * Gets all active users in the session
   */
  public getActiveUsers(): ARUser[] {
    const now = Date.now();
    return Array.from(this.users.values()).filter(
      user => user.isActive && now - user.lastUpdate < this.options.inactivityTimeout!
    );
  }

  private startHeartbeat(): void {
    if (this.heartbeatInterval) return;

    this.heartbeatInterval = setInterval(() => {
      if (this.currentUser) {
        this.currentUser.lastUpdate = Date.now();
        this.emit('heartbeat', this.currentUser);
      }
    }, this.options.heartbeatInterval);
  }

  /**
   * Ends the current user's session
   */
  public endSession(): void {
    if (!this.currentUser) return;

    this.currentUser.isActive = false;
    this.emit('userLeft', this.currentUser);

    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
      this.heartbeatInterval = null;
    }

    this.currentUser = null;
  }
}