import pkgPg from 'pg';
import { PGDATABASE, PGHOST, PGPASSWORD, PGPORT, PGUSER, SESSION_TIMEOUT, VLAN_ID, MAX_DOWN, MAX_UP } from '../config/env.js';

const { Pool } = pkgPg;
export const pool = new Pool({ host: PGHOST, port: PGPORT, database: PGDATABASE, user: PGUSER, password: PGPASSWORD });

export async function readUsersFromDb() {
  const client = await pool.connect();
  try {
    const q = `
      SELECT rc.username,
             rc.value AS password,
             EXISTS (
                SELECT 1 FROM radcheck r2
                WHERE r2.username = rc.username AND r2.attribute = 'Auth-Type' AND r2.value = 'Reject'
             ) AS disabled,
             COALESCE((
                SELECT rr.value FROM radreply rr
                WHERE rr.username = rc.username AND rr.attribute = 'Tunnel-Private-Group-Id'
                ORDER BY rr.id DESC LIMIT 1
             ), $1) AS vlan
      FROM radcheck rc
      WHERE rc.attribute = 'Cleartext-Password'
      ORDER BY rc.username ASC`;
    const { rows } = await client.query(q, [String(VLAN_ID)]);
    return rows.map(r => ({ username: r.username, password: r.password, vlan: String(r.vlan), disabled: !!r.disabled }));
  } finally {
    client.release();
  }
}

export async function upsertUserToDb(user) {
  const { username, password, vlan, disabled } = user;
  const client = await pool.connect();
  try {
    await client.query('BEGIN');
    await client.query("DELETE FROM radcheck WHERE username = $1 AND attribute = 'Cleartext-Password'", [username]);
    await client.query(
      "INSERT INTO radcheck (username, attribute, op, value) VALUES ($1,'Cleartext-Password',':=',$2)",
      [username, password]
    );
    await client.query("DELETE FROM radcheck WHERE username = $1 AND attribute = 'Auth-Type'", [username]);
    if (disabled) {
      await client.query(
        "INSERT INTO radcheck (username, attribute, op, value) VALUES ($1,'Auth-Type',':=','Reject')",
        [username]
      );
    }
    const attrs = [
      ['Tunnel-Type', 'VLAN'],
      ['Tunnel-Medium-Type', 'IEEE-802'],
      ['Tunnel-Private-Group-Id', String(vlan || VLAN_ID)],
      ['WISPr-Bandwidth-Max-Down', String(MAX_DOWN)],
      ['WISPr-Bandwidth-Max-Up', String(MAX_UP)],
    ];
    if (SESSION_TIMEOUT > 0) {
      attrs.push(['Session-Timeout', String(SESSION_TIMEOUT)]);
    }
    await client.query(
      "DELETE FROM radreply WHERE username = $1 AND attribute IN ('Tunnel-Type','Tunnel-Medium-Type','Tunnel-Private-Group-Id','WISPr-Bandwidth-Max-Down','WISPr-Bandwidth-Max-Up','Session-Timeout')",
      [username]
    );
    for (const [attr, val] of attrs) {
      await client.query(
        "INSERT INTO radreply (username, attribute, op, value) VALUES ($1,$2,':=',$3)",
        [username, attr, String(val)]
      );
    }
    await client.query('COMMIT');
  } catch (e) {
    await client.query('ROLLBACK');
    throw e;
  } finally {
    client.release();
  }
}

export async function deleteUserFromDb(username) {
  const client = await pool.connect();
  try {
    await client.query('BEGIN');
    await client.query('DELETE FROM radcheck WHERE username = $1', [username]);
    await client.query('DELETE FROM radreply WHERE username = $1', [username]);
    await client.query('COMMIT');
  } catch (e) {
    await client.query('ROLLBACK');
    throw e;
  } finally {
    client.release();
  }
}

