/**
 * Per-session gating state machine.
 *
 * Tracks whether a session has gone through the prompt selection flow.
 * When gated, only begin_session is accessible. After ungating, all tools work.
 */

import type { PromptIndexEntry, TagMatchResult } from './tag-matcher.js';

export interface SessionState {
  gated: boolean;
  tags: string[];
  retrievedPrompts: Set<string>;
  briefing: string | null;
}

export class SessionGate {
  private sessions = new Map<string, SessionState>();

  /** Create a new session. Starts gated if the project is gated. */
  createSession(sessionId: string, projectGated: boolean): void {
    this.sessions.set(sessionId, {
      gated: projectGated,
      tags: [],
      retrievedPrompts: new Set(),
      briefing: null,
    });
  }

  /** Get session state. Returns null if session doesn't exist. */
  getSession(sessionId: string): SessionState | null {
    return this.sessions.get(sessionId) ?? null;
  }

  /** Check if a session is currently gated. Unknown sessions are treated as ungated. */
  isGated(sessionId: string): boolean {
    return this.sessions.get(sessionId)?.gated ?? false;
  }

  /** Ungate a session after prompt selection is complete. */
  ungate(sessionId: string, tags: string[], matchResult: TagMatchResult): void {
    const session = this.sessions.get(sessionId);
    if (!session) return;

    session.gated = false;
    session.tags = [...session.tags, ...tags];

    // Track which prompts have been sent
    for (const p of matchResult.fullContent) {
      session.retrievedPrompts.add(p.name);
    }
  }

  /** Record additional prompts retrieved via read_prompts. */
  addRetrievedPrompts(sessionId: string, tags: string[], promptNames: string[]): void {
    const session = this.sessions.get(sessionId);
    if (!session) return;

    session.tags = [...session.tags, ...tags];
    for (const name of promptNames) {
      session.retrievedPrompts.add(name);
    }
  }

  /** Filter out prompts already sent to avoid duplicates. */
  filterAlreadySent(sessionId: string, prompts: PromptIndexEntry[]): PromptIndexEntry[] {
    const session = this.sessions.get(sessionId);
    if (!session) return prompts;
    return prompts.filter((p) => !session.retrievedPrompts.has(p.name));
  }

  /** Remove a session (cleanup on disconnect). */
  removeSession(sessionId: string): void {
    this.sessions.delete(sessionId);
  }
}
