/**
 * routes/option-consent.js — per-connection Oracle option licensing consent API.
 *
 * Owns: reading + recording the customer's explicit attestation that a given
 *       Oracle option (Diagnostics Pack, Tuning Pack, …) is licensed on a
 *       specific connection. This is the authorization the ADDM gate consults.
 * Does NOT own: the gate itself (routes/addm.js), or detection of what Oracle
 *       reports — detection is evidence shown to the human, never authorization.
 *
 * Mounted at /api/connections (see server.js).
 *   GET  /api/connections/:connId/option-consent            — all states + log
 *   POST /api/connections/:connId/option-consent            — grant/deny + log
 *
 * Ownership: every route confirms the connection belongs to req.user before
 * reading or writing, same pattern as routes/addm.js getConnectionForAddm().
 */

'use strict';

const express = require('express');
const pool = require('../db/index');
const { requireAuth } = require('../middleware/auth');
const consentDb = require('../db/option-consent');

const router = express.Router();

// Confirm the connection belongs to this user. Returns the row or null.
async function ownedConnection(connId, userId) {
  const { rows } = await pool.query(
    `SELECT id FROM oracle_connections WHERE id = :p1 AND user_id = :p2`,
    { p1: connId, p2: userId }
  );
  return rows[0] || null;
}

// GET /api/connections/:connId/option-consent
// Current consent state for every option on this connection + recent audit log.
router.get('/:connId/option-consent', requireAuth, async (req, res) => {
  const connId = parseInt(req.params.connId, 10);
  if (!connId) return res.status(400).json({ error: 'Invalid connection id' });
  try {
    if (!(await ownedConnection(connId, req.user.id))) {
      return res.status(404).json({ error: 'Connection not found' });
    }
    const [consents, log] = await Promise.all([
      consentDb.listForConnection(connId),
      consentDb.getLog(connId, 50),
    ]);
    res.json({ connection_id: connId, consents, log });
  } catch (err) {
    console.error('[option-consent] GET error:', err.message);
    res.status(500).json({ error: 'Failed to load consent state' });
  }
});

// GET /api/connections/:connId/pack-access
// Reads control_management_pack_access from the database and reports it next to
// the customer's attestation.
//
// WHY THIS IS WORTH SHOWING. The parameter is already read in several places
// (oracle-client.js, performance-advisor.js, oracle-proxy.py) but only ever as a
// fallback GUESS at whether the packs are licensed — the exact inference
// db/option-consent.js exists to stop making. The value itself is thrown away.
//
// Surfaced instead of inferred from, it answers a question the attestation alone
// cannot: what the database is actually configured to permit. The two disagree in
// ways that matter:
//
//   attested "not licensed" + parameter DIAGNOSTIC+TUNING
//       → the packs are ARMED on a database you say you have not bought. AWR keeps
//         collecting and any DBA, script or tool that reads it creates usage. This
//         is the audit-exposure case, and the fix is ALTER SYSTEM ... = 'NONE'.
//   attested "licensed" + parameter NONE
//       → you are entitled but the database has the features switched off, so AWR
//         reads will fail and the reason will look like a TuneVault bug.
//
// Read-only, and V$PARAMETER carries no pack requirement of its own.
router.get('/:connId/pack-access', requireAuth, async (req, res) => {
  const connId = parseInt(req.params.connId, 10);
  if (!connId) return res.status(400).json({ error: 'Invalid connection id' });
  try {
    if (!(await ownedConnection(connId, req.user.id))) {
      return res.status(404).json({ error: 'Connection not found' });
    }
    // Reuse the SQL Console's execution path rather than adding a fourth one —
    // it already handles proxy / direct-TCP / SSH and read-only validation.
    const { getConnParams, executeSQL } = require('./console');
    const connParams = await getConnParams(connId, req.user.id);
    if (!connParams) return res.status(404).json({ error: 'Connection not found' });

    const result = await executeSQL(
      connParams,
      "SELECT value FROM v$parameter WHERE name = 'control_management_pack_access'",
      1, 15000, req.user.id
    );
    const row = (result && result.rows && result.rows[0]) || null;
    const raw = row ? String(Object.values(row)[0] ?? '').trim() : '';
    res.json({
      connection_id: connId,
      value: raw || null,                       // e.g. DIAGNOSTIC+TUNING | DIAGNOSTIC | NONE
      normalized: raw ? raw.toUpperCase() : null,
      checked_at: new Date().toISOString(),
    });
  } catch (err) {
    // Never fail the licensing panel because the database was unreachable — the
    // attestation is the record of truth; this is corroboration.
    console.warn('[option-consent] pack-access read failed for conn %s: %s', connId, err.message);
    res.json({ connection_id: connId, value: null, normalized: null, error: 'unavailable' });
  }
});

// POST /api/connections/:connId/option-consent
// Body: { option_key, state: 'granted'|'denied'|'unset', source?, evidence? }
// Records the attestation and appends an audit-log row.
router.post('/:connId/option-consent', requireAuth, async (req, res) => {
  const connId = parseInt(req.params.connId, 10);
  if (!connId) return res.status(400).json({ error: 'Invalid connection id' });

  const { option_key, state, source, evidence } = req.body || {};
  if (!option_key || !consentDb.VALID_OPTIONS.has(option_key)) {
    return res.status(400).json({ error: 'Unknown or missing option_key' });
  }
  if (!state || !consentDb.VALID_STATES.has(state)) {
    return res.status(400).json({ error: 'Invalid or missing state' });
  }

  try {
    if (!(await ownedConnection(connId, req.user.id))) {
      return res.status(404).json({ error: 'Connection not found' });
    }
    const row = await consentDb.setConsent(connId, option_key, state, {
      actor:    req.user.id,
      source:   source || 'settings',
      evidence: evidence || null,
      ip:       req.ip || (req.headers['x-forwarded-for'] || '').split(',')[0] || null,
    });
    res.json({ ok: true, consent: row });
  } catch (err) {
    console.error('[option-consent] POST error:', err.message);
    res.status(500).json({ error: 'Failed to record consent' });
  }
});

module.exports = router;
