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

class SessionStore {
  constructor() {
    this.sessions = new Map();
    this.profileIndex = new Map();
  }

  create(payload, customId, ttlMs) {
    const id = customId || uuid();
    const profileId = payload?.profile?.id ? String(payload.profile.id) : null;

    if (profileId && this.profileIndex.has(profileId)) {
      const previousId = this.profileIndex.get(profileId);
      if (previousId && previousId !== id) {
        this.delete(previousId);
      }
    }

    const session = {
      id,
      createdAt: Date.now(),
      updatedAt: Date.now(),
      expiresAt: ttlMs ? Date.now() + ttlMs : null,
      jobs: [],
      ...payload
    };
    this.sessions.set(id, session);

    if (profileId) {
      this.profileIndex.set(profileId, id);
    }

    return session;
  }

  get(id) {
    const session = this.sessions.get(id);
    if (!session) {
      return null;
    }

    if (session.expiresAt && session.expiresAt < Date.now()) {
      this.delete(id);
      return null;
    }

    return session;
  }

  getByProfile(profileId) {
    const key = profileId ? String(profileId) : null;
    if (!key) {
      return null;
    }
    const id = this.profileIndex.get(key);
    return id ? this.get(id) : null;
  }

  update(id, patch) {
    const session = this.get(id);
    if (!session) {
      return null;
    }
    Object.assign(session, patch, { updatedAt: Date.now() });
    return session;
  }

  attachJob(id, job) {
    const session = this.get(id);
    if (!session) {
      return;
    }
    session.jobs.push(job);
  }

  clearJobs(id) {
    const session = this.get(id);
    if (!session || !Array.isArray(session.jobs)) {
      return;
    }
    session.jobs.forEach((job) => {
      if (job && typeof job.stop === 'function') {
        job.stop();
      }
    });
    session.jobs = [];
  }

  delete(id) {
    const session = this.sessions.get(id);
    if (session) {
      this.clearJobs(id);
      const profileId = session.profile?.id ? String(session.profile.id) : null;
      if (profileId && this.profileIndex.get(profileId) === id) {
        this.profileIndex.delete(profileId);
      }
    }
    this.sessions.delete(id);
  }

  list() {
    return Array.from(this.sessions.values());
  }
}

module.exports = new SessionStore();
