const { v4: uuidv4 } = require('uuid');

const VALID_STATUSES = new Set(['pending', 'active', 'warning', 'suspended', 'exited', 'slashed']);

class NodeParticipant {
  constructor(payload = {}) {
    const now = new Date().toISOString();

    this.id = payload.id || payload.nodeId || uuidv4();
    this.nodeId = payload.nodeId || this.id;
    this.userId = payload.userId || null;
    this.userIdHash = payload.userIdHash || null;
    this.serviceName = payload.serviceName || 'UNKNOWN';
    this.deviceName = payload.deviceName || payload.serviceName || 'UNKNOWN Node';
    this.pcName = payload.pcName || null;
    this.clientVersion = payload.clientVersion || null;
    this.endpoint = payload.endpoint || null;
    this.role = payload.role || 'NODE_PARTICIPANT';
    this.status = VALID_STATUSES.has(payload.status) ? payload.status : 'pending';
    this.pledgedPoint = Number(payload.pledgedPoint || 0);
    this.lockedPoint = Number(payload.lockedPoint || 0);
    this.slashPoint = Number(payload.slashPoint || 0);
    this.rewardPoint = Number(payload.rewardPoint || 0);
    this.storageLimitBytes = Number(payload.storageLimitBytes || payload.maxStorageBytes || 0);
    this.usedStorageBytes = Number(payload.usedStorageBytes || 0);
    this.availableStorageBytes = Number(payload.availableStorageBytes || Math.max(0, this.storageLimitBytes - this.usedStorageBytes));
    this.uptimeScore = Number(payload.uptimeScore || 0);
    this.proofSuccessRate = Number(payload.proofSuccessRate || 0);
    this.restoreSuccessRate = Number(payload.restoreSuccessRate || 0);
    this.lastHeartbeatAt = payload.lastHeartbeatAt || null;
    this.lastProofAt = payload.lastProofAt || null;
    this.joinedAt = payload.joinedAt || now;
    this.exitedAt = payload.exitedAt || null;
    this.warningCount = Number(payload.warningCount || 0);
    this.slashCount = Number(payload.slashCount || 0);
    this.metadata = payload.metadata && typeof payload.metadata === 'object' ? payload.metadata : {};
  }

  applyHeartbeat(payload = {}) {
    this.status = payload.status && VALID_STATUSES.has(payload.status) ? payload.status : 'active';
    this.lastHeartbeatAt = new Date().toISOString();

    if (payload.clientVersion) this.clientVersion = payload.clientVersion;
    if (payload.pcName) this.pcName = payload.pcName;
    if (payload.deviceName) this.deviceName = payload.deviceName;
    if (payload.usedStorageBytes !== undefined) this.usedStorageBytes = Number(payload.usedStorageBytes || 0);
    if (payload.availableStorageBytes !== undefined) this.availableStorageBytes = Number(payload.availableStorageBytes || 0);
    if (payload.storageLimitBytes !== undefined) this.storageLimitBytes = Number(payload.storageLimitBytes || 0);
    if (payload.proofSuccessRate !== undefined) this.proofSuccessRate = Number(payload.proofSuccessRate || 0);
    if (payload.restoreSuccessRate !== undefined) this.restoreSuccessRate = Number(payload.restoreSuccessRate || 0);
  }
}

NodeParticipant.VALID_STATUSES = VALID_STATUSES;

module.exports = NodeParticipant;
