import { getDb, queryOne, queryAll, execute } from '../db/database';
import type { RelayNode } from '@network-tool/shared-types';

export class NodeService {
  async registerNode(data: { name: string; host: string; port: number }): Promise<RelayNode> {
    const db = await getDb();
    const result = execute(db,
      "INSERT INTO relay_nodes (name, host, port, status, load) VALUES (?, ?, ?, 'offline', 0)",
      [data.name, data.host, data.port]
    );
    return queryOne<RelayNode>(db, 'SELECT * FROM relay_nodes WHERE id = ?', [result.lastInsertRowid])!;
  }

  async heartbeat(nodeId: number, data: { load: number; status: 'online' | 'offline' | 'busy' }): Promise<RelayNode | null> {
    const db = await getDb();
    const result = execute(db,
      "UPDATE relay_nodes SET status = ?, load = ?, last_heartbeat_at = datetime('now') WHERE id = ?",
      [data.status, data.load, nodeId]
    );
    if (result.changes === 0) return null;
    return queryOne<RelayNode>(db, 'SELECT * FROM relay_nodes WHERE id = ?', [nodeId]);
  }

  async getAllNodes(): Promise<RelayNode[]> {
    const db = await getDb();
    return queryAll<RelayNode>(db, 'SELECT * FROM relay_nodes ORDER BY last_heartbeat_at DESC');
  }

  async getAvailableNodes(): Promise<RelayNode[]> {
    const db = await getDb();
    return queryAll<RelayNode>(db,
      "SELECT * FROM relay_nodes WHERE status = 'online' AND load < 100 ORDER BY load ASC, last_heartbeat_at DESC"
    );
  }

  async getNodeById(nodeId: number): Promise<RelayNode | null> {
    const db = await getDb();
    return queryOne<RelayNode>(db, 'SELECT * FROM relay_nodes WHERE id = ?', [nodeId]);
  }

  async deleteNode(nodeId: number): Promise<boolean> {
    const db = await getDb();
    const result = execute(db, 'DELETE FROM relay_nodes WHERE id = ?', [nodeId]);
    return result.changes > 0;
  }

  async cleanupStaleNodes(timeoutMinutes = 5): Promise<void> {
    const db = await getDb();
    execute(db,
      "UPDATE relay_nodes SET status = 'offline' WHERE status != 'offline' AND last_heartbeat_at < datetime('now', '-' || ? || ' minutes')",
      [timeoutMinutes]
    );
  }
}
