import type { WebSocket } from '@fastify/websocket';
import type { Actor } from '../auth/dev-stub.js';
import { dispatch } from '../rpc/dispatcher.js';
import type { RpcRequest, ServerPush } from '../rpc/types.js';

export class Session {
  readonly id: string;
  readonly actor: Actor;
  readonly socket: WebSocket;
  // Подписки на таблицы (для фильтрации changelog push'а)
  readonly subscribed = new Set<string>();

  constructor(socket: WebSocket, actor: Actor) {
    this.id = crypto.randomUUID();
    this.socket = socket;
    this.actor = actor;
  }

  async handleMessage(raw: string): Promise<void> {
    let msg: RpcRequest;
    try {
      msg = JSON.parse(raw) as RpcRequest;
    } catch {
      this.send({ id: 'parse-error', ok: false, error: { code: 'BAD_JSON', message: 'invalid JSON' } } as any);
      return;
    }
    if (msg.method !== 'call' || !msg.id || !msg.name) {
      this.send({ id: msg.id ?? 'invalid', ok: false, error: { code: 'BAD_REQUEST', message: 'expected {id, method:"call", name, params?}' } } as any);
      return;
    }
    const resp = await dispatch(msg, this.actor.userId);
    this.send(resp);
  }

  push(p: ServerPush): void {
    if (p.type === 'changelog' && !this.subscribed.has(p.table)) return;
    this.send(p);
  }

  private send(obj: unknown): void {
    try {
      this.socket.send(JSON.stringify(obj));
    } catch (e) {
      console.error('[ws] send failed', e);
    }
  }
}
