import type Database from 'better-sqlite3';
import bcrypt from 'bcryptjs';
import { randomBytes } from 'node:crypto';

export const SESSION_COOKIE = 'session';
const SESSION_DAYS = 7;

export type Role = 'admin' | 'editor';

export function hashPassword(plain: string): string {
  return bcrypt.hashSync(plain, 12);
}

export function verifyPassword(plain: string, hash: string): boolean {
  return bcrypt.compareSync(plain, hash);
}

export function createUser(db: Database.Database, username: string, password: string, role: Role = 'admin'): number {
  const res = db.prepare('INSERT INTO users (username, password_hash, role) VALUES (?, ?, ?)')
    .run(username, hashPassword(password), role);
  return Number(res.lastInsertRowid);
}

export function login(db: Database.Database, username: string, password: string): string | null {
  const user = db.prepare('SELECT * FROM users WHERE username = ?').get(username) as
    | { id: number; password_hash: string } | undefined;
  if (!user || !verifyPassword(password, user.password_hash)) return null;
  const token = randomBytes(32).toString('hex');
  db.prepare(
    `INSERT INTO sessions (token, user_id, expires_at) VALUES (?, ?, datetime('now', '+${SESSION_DAYS} days'))`
  ).run(token, user.id);
  return token;
}

export function getSessionUser(db: Database.Database, token: string): { id: number; username: string; role: string } | null {
  const row = db.prepare(
    `SELECT s.token, s.expires_at, u.id, u.username, u.role
     FROM sessions s JOIN users u ON u.id = s.user_id WHERE s.token = ?`
  ).get(token) as { token: string; expires_at: string; id: number; username: string; role: string } | undefined;
  if (!row) return null;
  if (row.expires_at <= new Date().toISOString().slice(0, 19).replace('T', ' ')) {
    db.prepare('DELETE FROM sessions WHERE token = ?').run(token);
    return null;
  }
  return { id: row.id, username: row.username, role: row.role };
}

export function logout(db: Database.Database, token: string): void {
  db.prepare('DELETE FROM sessions WHERE token = ?').run(token);
}

// Percorsi admin consentiti anche al ruolo editor.
const EDITOR_ALLOWED = [/^\/admin\/content(\/|$)/, /^\/api\/admin\/content(\/|$)/, /^\/admin\/logout$/];

export function canAccessAdminPath(role: string, pathname: string): boolean {
  if (role === 'admin') return true;
  return EDITOR_ALLOWED.some((re) => re.test(pathname));
}
