'use strict';

const { makePrincipalKey, normalizePrincipal } = require('./policy');

class ChannelSessionBindings {
  constructor({ initial = [] } = {}) {
    this.bindings = new Map();
    for (const binding of initial || []) {
      this.bind(binding.principal || binding, binding.sessionId, binding.metadata || {});
    }
  }

  bind(principal, sessionId, metadata = {}) {
    if (!sessionId) throw new Error('sessionId is required');
    const normalized = normalizePrincipal(principal);
    const key = makePrincipalKey(normalized);
    const record = {
      key,
      principal: normalized,
      sessionId,
      metadata: { ...metadata },
      updatedAt: new Date().toISOString(),
    };
    this.bindings.set(key, record);
    return { ...record, principal: { ...record.principal }, metadata: { ...record.metadata } };
  }

  resolve(principal) {
    const key = makePrincipalKey(principal);
    const record = this.bindings.get(key);
    return record ? { ...record, principal: { ...record.principal }, metadata: { ...record.metadata } } : null;
  }

  unbind(principal) {
    return this.bindings.delete(makePrincipalKey(principal));
  }

  list({ channel = null } = {}) {
    return [...this.bindings.values()]
      .filter(record => !channel || record.principal.channel === channel)
      .map(record => ({ ...record, principal: { ...record.principal }, metadata: { ...record.metadata } }));
  }

  toJSON() {
    return this.list();
  }
}

module.exports = {
  ChannelSessionBindings,
};
