<?php
/**
 * Admin Issues API.
 * Consumed by web-files/pages/issues.php.
 *
 * Actions (GET): list, get, list_suppressions
 * Actions (POST): mark_fixed, mark_ignored, bulk_update, un_suppress
 *
 * Permission: root only — enforced by the blanket $AUTH_USER check below.
 * Per-row ownership helpers (can_view_issue / can_modify_issue) live in
 * permission_checker.php and are used by the customer API (not here).
 *
 * CSRF on POST is enforced globally by auto-prepend.php.
 */
require_once('/docker/whp/web/libs/permission_checker.php');
require_once('/docker/whp/web/libs/mysqlmgmt.php');
require_once('/docker/whp/web/libs/ai-monitor-explain.php');

header('Content-Type: application/json');

if (!defined('AUTH_USER') || AUTH_USER !== 'root') {
    http_response_code(403);
    echo json_encode(['success' => false, 'error' => 'Admin only']);
    exit;
}

$db = (new mysqlmgmt())->getMySQLConnection();
if (!$db) {
    http_response_code(500);
    echo json_encode(['success' => false, 'error' => 'Database unavailable']);
    exit;
}

$method = $_SERVER['REQUEST_METHOD'];
$action = $_REQUEST['action'] ?? '';
$AUDIT_USER = AUTH_USER;

try {
    if ($method === 'GET' && $action === 'list') {
        echo json_encode(action_list($db));
        exit;
    }
    if ($method === 'GET' && $action === 'get') {
        echo json_encode(action_get($db, (int)($_GET['id'] ?? 0)));
        exit;
    }
    if ($method === 'GET' && $action === 'list_suppressions') {
        echo json_encode(action_list_suppressions($db));
        exit;
    }
    if ($method === 'POST' && $action === 'mark_fixed') {
        echo json_encode(action_mark($db, (int)($_POST['id'] ?? 0), 'fixed', $AUDIT_USER));
        exit;
    }
    if ($method === 'POST' && $action === 'mark_ignored') {
        echo json_encode(action_mark_ignored(
            $db,
            (int)($_POST['id'] ?? 0),
            !empty($_POST['suppress']),
            trim((string)($_POST['reason'] ?? '')),
            $AUDIT_USER
        ));
        exit;
    }
    if ($method === 'POST' && $action === 'bulk_update') {
        $ids = json_decode($_POST['ids'] ?? '[]', true) ?: [];
        echo json_encode(action_bulk($db, $ids, (string)($_POST['to_status'] ?? ''), $AUDIT_USER));
        exit;
    }
    if ($method === 'POST' && $action === 'bulk_delete') {
        $ids = json_decode($_POST['ids'] ?? '[]', true) ?: [];
        echo json_encode(action_bulk_delete($db, $ids));
        exit;
    }
    if ($method === 'POST' && $action === 'un_suppress') {
        echo json_encode(action_un_suppress($db, (int)($_POST['id'] ?? 0)));
        exit;
    }
    if ($method === 'POST' && $action === 'explain_issue') {
        echo json_encode(action_explain_issue(
            $db,
            (int)($_POST['id'] ?? 0),
            !empty($_POST['regenerate'])
        ));
        exit;
    }
    http_response_code(400);
    echo json_encode(['success' => false, 'error' => 'Unknown action']);
} catch (Throwable $e) {
    error_log('issues.php error: ' . $e->getMessage());
    http_response_code(500);
    echo json_encode(['success' => false, 'error' => 'Server error']);
}

// ----- actions -----

function action_list(PDO $db): array {
    $where = [];
    $params = [];
    $scope      = $_GET['scope']    ?? 'all';
    $status     = $_GET['status']   ?? 'open';
    $severity   = $_GET['severity'] ?? '';
    $source     = $_GET['source']   ?? '';
    $site_id    = $_GET['site_id']  ?? '';
    $sig_prefix = trim((string)($_GET['signature'] ?? ''));
    $page       = max(1, (int)($_GET['page'] ?? 1));
    $per        = 25;

    if ($scope === 'site')   { $where[] = 'i.site_id IS NOT NULL'; }
    if ($scope === 'server') { $where[] = 'i.site_id IS NULL'; }
    if ($status !== 'all')   { $where[] = 'i.status = ?'; $params[] = $status; }
    if ($severity !== '')    { $where[] = 'i.severity = ?'; $params[] = $severity; }
    if ($source !== '')      { $where[] = 'i.source = ?'; $params[] = $source; }
    if ($site_id !== '')     { $where[] = 'i.site_id = ?'; $params[] = (int)$site_id; }
    if ($sig_prefix !== '')  { $where[] = 'i.signature LIKE ?'; $params[] = $sig_prefix . '%'; }

    $where_sql = $where ? ('WHERE ' . implode(' AND ', $where)) : '';
    $count_stmt = $db->prepare("SELECT COUNT(*) FROM whp.ai_monitor_issues i {$where_sql}");
    $count_stmt->execute($params);
    $total = (int)$count_stmt->fetchColumn();

    $offset = ($page - 1) * $per;
    $stmt = $db->prepare("
        SELECT i.*, d.domain_name AS primary_domain, s.site_name
        FROM whp.ai_monitor_issues i
        LEFT JOIN whp.sites s ON s.id = i.site_id
        LEFT JOIN whp.domains d ON d.id = s.primary_domain_id
        {$where_sql}
        ORDER BY (i.status='open') DESC, i.severity='critical' DESC, i.last_seen DESC
        LIMIT {$per} OFFSET {$offset}
    ");
    $stmt->execute($params);
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

    $summary = $db->query("
        SELECT
          SUM(status='open' AND severity='critical') AS critical,
          SUM(status='open' AND severity='warning')  AS warning,
          SUM(status='open' AND auto_resolved_at IS NOT NULL) AS auto_resolved,
          (SELECT COUNT(*) FROM whp.ai_monitor_suppressions) AS suppressions
        FROM whp.ai_monitor_issues
    ")->fetch(PDO::FETCH_ASSOC);

    return ['success' => true, 'rows' => $rows, 'total' => $total,
            'page' => $page, 'per_page' => $per, 'summary' => $summary];
}

function action_get(PDO $db, int $id): array {
    $stmt = $db->prepare("
        SELECT i.*, d.domain_name AS primary_domain, s.site_name
        FROM whp.ai_monitor_issues i
        LEFT JOIN whp.sites s ON s.id = i.site_id
        LEFT JOIN whp.domains d ON d.id = s.primary_domain_id
        WHERE i.id = ?");
    $stmt->execute([$id]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$row) return ['success' => false, 'error' => 'Not found'];
    return ['success' => true, 'row' => $row];
}

function action_mark(PDO $db, int $id, string $to_status, string $user): array {
    if (!in_array($to_status, ['fixed', 'ignored'], true)) {
        return ['success' => false, 'error' => 'Invalid status'];
    }
    $stmt = $db->prepare("
        UPDATE whp.ai_monitor_issues
        SET status = ?, status_changed_by = ?, status_changed_at = NOW()
        WHERE id = ?");
    $stmt->execute([$to_status, $user, $id]);
    return ['success' => true, 'affected' => $stmt->rowCount()];
}

function action_mark_ignored(PDO $db, int $id, bool $suppress, string $reason, string $user): array {
    $db->beginTransaction();
    try {
        $stmt = $db->prepare("
            UPDATE whp.ai_monitor_issues
            SET status = 'ignored', status_changed_by = ?, status_changed_at = NOW()
            WHERE id = ?");
        $stmt->execute([$user, $id]);

        if ($suppress) {
            $s = $db->prepare("SELECT signature, site_id FROM whp.ai_monitor_issues WHERE id = ?");
            $s->execute([$id]);
            $r = $s->fetch(PDO::FETCH_ASSOC);
            if ($r) {
                $ins = $db->prepare("
                    INSERT IGNORE INTO whp.ai_monitor_suppressions
                        (site_id, signature, scope, suppressed_by_user, reason)
                    VALUES (?, ?, ?, ?, ?)");
                $ins->execute([
                    $r['site_id'],
                    $r['signature'],
                    $r['site_id'] ? 'site' : 'server',
                    $user,
                    $reason ?: null,
                ]);
            }
        }
        $db->commit();
        return ['success' => true];
    } catch (Throwable $e) {
        $db->rollBack();
        throw $e;
    }
}

function action_bulk(PDO $db, array $ids, string $to_status, string $user): array {
    if (!$ids || !in_array($to_status, ['fixed', 'ignored'], true)) {
        return ['success' => false, 'error' => 'Invalid input'];
    }
    $ids = array_values(array_filter(array_map('intval', $ids), fn($n) => $n > 0));
    if (!$ids) {
        return ['success' => false, 'error' => 'Invalid ids'];
    }
    $placeholders = implode(',', array_fill(0, count($ids), '?'));
    $stmt = $db->prepare("
        UPDATE whp.ai_monitor_issues
        SET status = ?, status_changed_by = ?, status_changed_at = NOW()
        WHERE id IN ({$placeholders})");
    $stmt->execute(array_merge([$to_status, $user], $ids));
    return ['success' => true, 'affected' => $stmt->rowCount()];
}

function action_bulk_delete(PDO $db, array $ids): array {
    $ids = array_values(array_filter(array_map('intval', $ids), fn($n) => $n > 0));
    if (!$ids) {
        return ['success' => false, 'error' => 'Invalid ids'];
    }
    $placeholders = implode(',', array_fill(0, count($ids), '?'));
    $stmt = $db->prepare("DELETE FROM whp.ai_monitor_issues WHERE id IN ({$placeholders})");
    $stmt->execute($ids);
    return ['success' => true, 'affected' => $stmt->rowCount()];
}

function action_list_suppressions(PDO $db): array {
    // Pull the most-recent matching Issue's title + category so the row is
    // recognizable instead of just a signature hash.
    $stmt = $db->query("
        SELECT sup.*, d.domain_name AS primary_domain, s.site_name,
               latest.title AS issue_title,
               latest.category AS issue_category,
               latest.severity AS issue_severity
        FROM whp.ai_monitor_suppressions sup
        LEFT JOIN whp.sites s ON s.id = sup.site_id
        LEFT JOIN whp.domains d ON d.id = s.primary_domain_id
        LEFT JOIN (
            SELECT i1.signature, i1.title, i1.category, i1.severity
            FROM whp.ai_monitor_issues i1
            JOIN (
                SELECT signature, MAX(id) AS max_id
                FROM whp.ai_monitor_issues GROUP BY signature
            ) latest_ids ON latest_ids.signature = i1.signature AND latest_ids.max_id = i1.id
        ) latest ON latest.signature = sup.signature
        ORDER BY sup.suppressed_at DESC");
    return ['success' => true, 'rows' => $stmt->fetchAll(PDO::FETCH_ASSOC)];
}

function action_un_suppress(PDO $db, int $id): array {
    $stmt = $db->prepare("DELETE FROM whp.ai_monitor_suppressions WHERE id = ?");
    $stmt->execute([$id]);
    return ['success' => true, 'affected' => $stmt->rowCount()];
}

/**
 * POST explain_issue: return (and cache) a plain-English explanation of an
 * issue. Root-only on this admin endpoint; the customer endpoint has its
 * own ownership-scoped copy.
 */
function action_explain_issue(PDO $db, int $id, bool $regenerate): array {
    if ($id <= 0) {
        return ['success' => false, 'error' => 'Missing issue id'];
    }
    $stmt = $db->prepare("SELECT * FROM whp.ai_monitor_issues WHERE id = ?");
    $stmt->execute([$id]);
    $issue = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$issue) {
        return ['success' => false, 'error' => 'Issue not found'];
    }
    if (!$regenerate && !empty($issue['user_explanation'])) {
        return ['success' => true,
                'explanation'  => $issue['user_explanation'],
                'cached'       => true,
                'generated_at' => $issue['user_explanation_at'] ?? null,
                'model'        => $issue['user_explanation_model'] ?? null];
    }
    $explain = ai_monitor_explain_issue($issue);
    if (!$explain['success']) {
        return ['success' => false, 'error' => $explain['error']];
    }
    $db->prepare("
        UPDATE whp.ai_monitor_issues
        SET user_explanation = ?, user_explanation_at = NOW(), user_explanation_model = ?
        WHERE id = ?
    ")->execute([$explain['explanation'], $explain['model'], $id]);

    return ['success' => true,
            'explanation' => $explain['explanation'],
            'cached'      => false,
            'model'       => $explain['model']];
}
