import { DatabaseSync } from 'node:sqlite';
import { randomBytes, createHash } from 'node:crypto';
import { mkdirSync, chmodSync } from 'node:fs';
import path from 'node:path';
const hash = value => createHash('sha256').update(value).digest('hex');
export class TrialAccess {
  constructor(filename) {
    if(filename!==':memory:')mkdirSync(path.dirname(filename),{recursive:true,mode:0o700});
    this.db=new DatabaseSync(filename);if(filename!==':memory:')chmodSync(filename,0o600);
    this.db.exec('CREATE TABLE IF NOT EXISTS trials(id TEXT PRIMARY KEY, used INTEGER NOT NULL DEFAULT 0, relay INTEGER NOT NULL DEFAULT 0); CREATE TABLE IF NOT EXISTS trial_issuance(ip TEXT, day TEXT, count INTEGER NOT NULL, PRIMARY KEY(ip,day));');
  }
  get(token){if(typeof token!=='string'||!/^[A-Za-z0-9_-]{43}$/.test(token))return null;return this.db.prepare('SELECT * FROM trials WHERE id=?').get(hash(token))||null;}
  issue(token,ip){let row=this.get(token);if(!row){const day=new Date().toISOString().slice(0,10),key=hash(ip||'unknown');this.db.prepare('DELETE FROM trial_issuance WHERE day<?').run(day);const count=this.db.prepare('SELECT count FROM trial_issuance WHERE ip=? AND day=?').get(key,day)?.count||0;if(count>=3)throw new Error('Trop de nouveaux essais depuis ce réseau aujourd’hui. Réutilisez votre navigateur habituel.');if(this.db.prepare('SELECT count(*) AS n FROM trials').get().n>=10000)throw new Error('Les essais sont momentanément complets.');token=randomBytes(32).toString('base64url');this.db.prepare('INSERT INTO trials(id) VALUES(?)').run(hash(token));this.db.prepare('INSERT INTO trial_issuance VALUES(?,?,1) ON CONFLICT(ip,day) DO UPDATE SET count=count+1').run(key,day);row=this.get(token);}return {token,remaining:3-row.used,relayRemaining:Math.max(0,1e9-row.relay)};}
  consume(token){return Boolean(this.db.prepare('UPDATE trials SET used=used+1 WHERE id=? AND used<3').run(hash(token)).changes);}
  consumeRelay(id,bytes){return Boolean(this.db.prepare('UPDATE trials SET relay=relay+? WHERE id=? AND relay+?<=1000000000').run(bytes,id,bytes).changes);}
  close(){this.db.close();}
}
