import Database from 'better-sqlite3';
import { randomBytes, scryptSync, timingSafeEqual, createHash } from 'crypto';
import * as fs from 'fs';
import * as path from 'path';

const DB_DIR = path.join(process.env.HOME || "", ".shooter");
const DB_PATH = path.join(DB_DIR, "shooter.db");
const SESSION_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
class ShareStore {
  db;
  constructor() {
    fs.mkdirSync(DB_DIR, { recursive: true });
    this.db = new Database(DB_PATH);
    this.db.pragma("journal_mode = WAL");
    this.db.exec(`
			CREATE TABLE IF NOT EXISTS terminal_shares (
				terminal_id   TEXT PRIMARY KEY,
				password_hash TEXT NOT NULL,
				mode          TEXT NOT NULL,
				created_at    INTEGER NOT NULL,
				updated_at    INTEGER NOT NULL
			);
			CREATE TABLE IF NOT EXISTS share_sessions (
				token_hash  TEXT PRIMARY KEY,
				terminal_id TEXT NOT NULL,
				created_at  INTEGER NOT NULL,
				expires_at  INTEGER NOT NULL
			)
		`);
    this.cleanup();
  }
  /** Purge expired sessions and shares whose terminal no longer exists. */
  cleanup() {
    this.db.prepare("DELETE FROM share_sessions WHERE expires_at < ?").run(Date.now());
    try {
      this.db.prepare("DELETE FROM terminal_shares WHERE terminal_id NOT IN (SELECT id FROM terminals)").run();
      this.db.prepare("DELETE FROM share_sessions WHERE terminal_id NOT IN (SELECT id FROM terminals)").run();
    } catch {
    }
  }
  /** Issue a new guest session for a shared terminal. Returns the raw token (stored hashed). */
  createSession(terminalId) {
    const token = randomBytes(32).toString("hex");
    const now = Date.now();
    const expiresAt = now + SESSION_TTL_MS;
    this.db.prepare(
      "INSERT INTO share_sessions (token_hash, terminal_id, created_at, expires_at) VALUES (?, ?, ?, ?)"
    ).run(hashToken(token), terminalId, now, expiresAt);
    return { expiresAt, token };
  }
  /** Delete all guest sessions for a terminal (password change / revoke). */
  deleteSessions(terminalId) {
    this.db.prepare("DELETE FROM share_sessions WHERE terminal_id = ?").run(terminalId);
  }
  /** Revoke a share: delete the share row and every guest session for it. */
  deleteShare(terminalId) {
    this.db.prepare("DELETE FROM terminal_shares WHERE terminal_id = ?").run(terminalId);
    this.deleteSessions(terminalId);
  }
  getShare(terminalId) {
    const row = this.db.prepare("SELECT * FROM terminal_shares WHERE terminal_id = ?").get(terminalId);
    return row ? rowToShare(row) : null;
  }
  /**
   * Resolve a guest bearer token to its terminal + mode.
   * Returns null if unknown, expired, or the share was revoked.
   */
  resolveToken(token) {
    if (!token) {
      return null;
    }
    const row = this.db.prepare(
      `SELECT s.terminal_id, s.expires_at, sh.mode
				 FROM share_sessions s
				 JOIN terminal_shares sh ON sh.terminal_id = s.terminal_id
				 WHERE s.token_hash = ?`
    ).get(hashToken(token));
    if (!row) {
      return null;
    }
    if (row.expires_at < Date.now()) {
      this.db.prepare("DELETE FROM share_sessions WHERE token_hash = ?").run(hashToken(token));
      return null;
    }
    return { mode: row.mode, terminalId: row.terminal_id };
  }
  /** Create or replace the share for a terminal. */
  setShare(record) {
    this.db.prepare(
      `INSERT OR REPLACE INTO terminal_shares
				 (terminal_id, password_hash, mode, created_at, updated_at)
				 VALUES (?, ?, ?, ?, ?)`
    ).run(record.terminalId, record.passwordHash, record.mode, record.createdAt, record.updatedAt);
  }
}
function hashPassword(password) {
  const salt = randomBytes(16).toString("hex");
  const hash = scryptSync(password, salt, 64).toString("hex");
  return `scrypt:${salt}:${hash}`;
}
function verifyPassword(password, stored) {
  const parts = stored.split(":");
  if (parts.length !== 3 || parts[0] !== "scrypt") {
    return false;
  }
  const expected = Buffer.from(parts[2], "hex");
  const actual = scryptSync(password, parts[1], 64);
  return expected.length === actual.length && timingSafeEqual(actual, expected);
}
function hashToken(token) {
  return createHash("sha256").update(token).digest("hex");
}
function rowToShare(row) {
  return {
    createdAt: row.created_at,
    mode: row.mode,
    passwordHash: row.password_hash,
    terminalId: row.terminal_id,
    updatedAt: row.updated_at
  };
}
const SS_GLOBAL_KEY = "__shooter_share_store";
const shareStore = globalThis[SS_GLOBAL_KEY] || new ShareStore();
globalThis[SS_GLOBAL_KEY] = shareStore;

export { hashPassword as h, shareStore as s, verifyPassword as v };
//# sourceMappingURL=share-store-B9jMpVg0.js.map
