<?php
/**
 * admin/empfaenger/empfaenger_bulk_ajax.php
 * ----------------------------------------------------------------------
 * AJAX Endpoint: Bulk-Aktionen für Empfänger (JSON Antwort)
 * ----------------------------------------------------------------------
 * Aktionen:
 *  • set_active           -> recipients.status = 'active'
 *  • set_inactive         -> recipients.status = 'inactive'
 *  • delete               -> recipients.status = 'unsubscribed' (kein Hard-Delete)
 *  • add_tag              -> recipient_tags (INSERT IGNORE)
 *  • remove_tag           -> recipient_tags (DELETE)
 *  • move_to_list         -> recipient_lists (DELETE source + INSERT target)
 *  • auto_tag_inactive    -> setzt Tag für "nie geöffnet/geklickt" (auf gefilterte Auswahl)
 *
 * Auto-Tagging (auto_tag_inactive):
 *  • Parameter:
 *      - tag_id (Pflicht)
 *      - list_id (optional; wenn gesetzt: nur Empfänger in dieser Liste)
 *      - dry_run (optional: 1 = nur zählen, nichts schreiben)
 *      - only_status (optional: 'active' Default; leer = kein Statusfilter)
 *
 * Logging:
 *  • ErrorLogger::logSqlSuccess / ErrorLogger::logSqlError
 *
 * Fehlerbehandlung:
 *  • try/catch + Transaktionen
 *  • Immer JSON zurückgeben
 */

session_start();
require_once __DIR__ . '/../../includes/init.php';
require_once __DIR__ . '/../../auth/AuthController.php';

header('Content-Type: application/json; charset=UTF-8');

$auth = new AuthController();
if (!$auth->isLoggedIn()) {
    http_response_code(403);
    echo json_encode(['success' => false, 'message' => 'Nicht autorisiert (403).']);
    exit;
}

$db = Database::getInstance();

/* =========================================================================
 * Helper: Einheitliche JSON-Ausgabe
 * ========================================================================= */
function jsonOut(bool $success, string $message, int $httpCode = 200, array $extra = []): void
{
    http_response_code($httpCode);
    echo json_encode(array_merge([
        'success' => $success,
        'message' => $message
    ], $extra));
    exit;
}

/* =========================================================================
 * Input validieren & normalisieren
 * ========================================================================= */
$action = (string)($_POST['action'] ?? '');

/**
 * recipient_ids[] sind für klassische Bulk-Aktionen Pflicht,
 * ABER NICHT für auto_tag_inactive (weil dort "alle gefilterten" gemeint ist).
 */
$idsRaw = $_POST['recipient_ids'] ?? [];
if (!is_array($idsRaw)) {
    $idsRaw = [];
}
$ids = array_values(array_filter(array_map('intval', $idsRaw), fn($v) => $v > 0));

if ($action === '') {
    jsonOut(false, 'Ungültige Anfrage: action fehlt.', 400);
}

try {
    $db->beginTransaction();

    /* ------------------------------------------------------------
     * set_active
     * ---------------------------------------------------------- */
    if ($action === 'set_active') {
        if (empty($ids)) {
            $db->rollBack();
            jsonOut(false, 'Keine Empfänger ausgewählt.', 400);
        }

        $in = implode(',', array_fill(0, count($ids), '?'));
        $sql = "UPDATE recipients SET status = 'active' WHERE id IN ($in)";
        $stmt = $db->prepare($sql);
        $stmt->execute($ids);

        ErrorLogger::logSqlSuccess('empfaenger_bulk_ajax | file: ' . __FILE__ . ' | message: UPDATE recipients status=active | count=' . count($ids));
        $db->commit();
        jsonOut(true, 'Empfänger wurden auf Aktiv gesetzt.');
    }

    /* ------------------------------------------------------------
     * set_inactive
     * ---------------------------------------------------------- */
    if ($action === 'set_inactive') {
        if (empty($ids)) {
            $db->rollBack();
            jsonOut(false, 'Keine Empfänger ausgewählt.', 400);
        }

        $in = implode(',', array_fill(0, count($ids), '?'));
        $sql = "UPDATE recipients SET status = 'inactive' WHERE id IN ($in)";
        $stmt = $db->prepare($sql);
        $stmt->execute($ids);

        ErrorLogger::logSqlSuccess('empfaenger_bulk_ajax | file: ' . __FILE__ . ' | message: UPDATE recipients status=inactive | count=' . count($ids));
        $db->commit();
        jsonOut(true, 'Empfänger wurden auf Inaktiv gesetzt.');
    }

    /* ------------------------------------------------------------
     * delete (unsubscribed)
     * ---------------------------------------------------------- */
    if ($action === 'delete') {
        if (empty($ids)) {
            $db->rollBack();
            jsonOut(false, 'Keine Empfänger ausgewählt.', 400);
        }

        $in = implode(',', array_fill(0, count($ids), '?'));
        $sql = "UPDATE recipients SET status = 'unsubscribed' WHERE id IN ($in)";
        $stmt = $db->prepare($sql);
        $stmt->execute($ids);

        ErrorLogger::logSqlSuccess('empfaenger_bulk_ajax | file: ' . __FILE__ . ' | message: UPDATE recipients status=unsubscribed | count=' . count($ids));
        $db->commit();
        jsonOut(true, 'Empfänger wurden abgemeldet (unsubscribed).');
    }

    /* ------------------------------------------------------------
     * add_tag
     * ---------------------------------------------------------- */
    if ($action === 'add_tag') {
        if (empty($ids)) {
            $db->rollBack();
            jsonOut(false, 'Keine Empfänger ausgewählt.', 400);
        }

        $tagId = (int)($_POST['tag_id'] ?? 0);
        if ($tagId <= 0) {
            $db->rollBack();
            jsonOut(false, 'Bitte einen gültigen Tag auswählen.', 400);
        }

        $sql = "INSERT IGNORE INTO recipient_tags (recipient_id, tag_id) VALUES (?, ?)";
        $stmt = $db->prepare($sql);

        foreach ($ids as $rid) {
            $stmt->execute([$rid, $tagId]);
        }

        ErrorLogger::logSqlSuccess('empfaenger_bulk_ajax | file: ' . __FILE__ . ' | message: INSERT recipient_tags tag_id=' . $tagId . ' | count=' . count($ids));
        $db->commit();
        jsonOut(true, 'Tag wurde den Empfängern hinzugefügt.');
    }

    /* ------------------------------------------------------------
     * remove_tag (NEU)
     * ---------------------------------------------------------- */
    if ($action === 'remove_tag') {
        if (empty($ids)) {
            $db->rollBack();
            jsonOut(false, 'Keine Empfänger ausgewählt.', 400);
        }

        $tagId = (int)($_POST['tag_id'] ?? 0);
        if ($tagId <= 0) {
            $db->rollBack();
            jsonOut(false, 'Bitte einen gültigen Tag auswählen.', 400);
        }

        $in = implode(',', array_fill(0, count($ids), '?'));
        $sql = "DELETE FROM recipient_tags WHERE tag_id = ? AND recipient_id IN ($in)";
        $stmt = $db->prepare($sql);
        $stmt->execute(array_merge([$tagId], $ids));
        $deleted = (int)$stmt->rowCount();

        ErrorLogger::logSqlSuccess('empfaenger_bulk_ajax | file: ' . __FILE__ . ' | message: DELETE recipient_tags tag_id=' . $tagId . ' | ids=' . count($ids) . ' | deleted=' . $deleted);
        $db->commit();
        jsonOut(true, "Tag wurde entfernt (deleted=$deleted).", 200, ['deleted' => $deleted]);
    }

    /* ------------------------------------------------------------
     * move_to_list
     * ---------------------------------------------------------- */
    if ($action === 'move_to_list') {
        if (empty($ids)) {
            $db->rollBack();
            jsonOut(false, 'Keine Empfänger ausgewählt.', 400);
        }

        $sourceListId = (int)($_POST['source_list_id'] ?? 0);
        $targetListId = (int)($_POST['target_list_id'] ?? 0);

        if ($sourceListId <= 0 || $targetListId <= 0) {
            $db->rollBack();
            jsonOut(false, 'Quelle/Ziel-Liste fehlt oder ungültig.', 400);
        }
        if ($sourceListId === $targetListId) {
            $db->rollBack();
            jsonOut(false, 'Quelle und Ziel sind identisch.', 400);
        }

        $in = implode(',', array_fill(0, count($ids), '?'));

        // 1) Quelle löschen
        $sqlDel = "DELETE FROM recipient_lists
                   WHERE list_id = ? AND recipient_id IN ($in)";
        $stmtDel = $db->prepare($sqlDel);
        $stmtDel->execute(array_merge([$sourceListId], $ids));
        $deleted = (int)$stmtDel->rowCount();

        ErrorLogger::logSqlSuccess('empfaenger_bulk_ajax | file: ' . __FILE__ . ' | message: DELETE recipient_lists source_list_id=' . $sourceListId . ' | ids=' . count($ids) . ' | deleted=' . $deleted);

        // 2) Ziel hinzufügen, wenn nicht vorhanden
        $sqlExists = "SELECT COUNT(*) FROM recipient_lists WHERE recipient_id = ? AND list_id = ?";
        $stmtExists = $db->prepare($sqlExists);

        $sqlIns = "INSERT INTO recipient_lists (recipient_id, list_id, subscribed_at, pause_token)
                   VALUES (?, ?, NOW(), ?)";
        $stmtIns = $db->prepare($sqlIns);

        $inserted = 0;
        foreach ($ids as $rid) {
            $stmtExists->execute([$rid, $targetListId]);
            $exists = (int)$stmtExists->fetchColumn();

            if ($exists === 0) {
                $pauseToken = bin2hex(random_bytes(32));
                $stmtIns->execute([$rid, $targetListId, $pauseToken]);
                $inserted += (int)$stmtIns->rowCount();
            }
        }

        ErrorLogger::logSqlSuccess('empfaenger_bulk_ajax | file: ' . __FILE__ . ' | message: INSERT recipient_lists target_list_id=' . $targetListId . ' | ids=' . count($ids) . ' | inserted=' . $inserted);

        $db->commit();
        jsonOut(true, "Empfänger verschoben: entfernt=$deleted, hinzugefügt=$inserted.", 200, [
            'deleted' => $deleted,
            'inserted' => $inserted
        ]);
    }

    /* ------------------------------------------------------------
     * auto_tag_inactive (NEU) – auf gefilterte Auswahl anwenden
     *
     * Idee:
     *  - "nie geöffnet/geklickt": last_opened_at IS NULL AND last_clicked_at IS NULL
     *  - optional: Liste einschränken (list_id)
     *  - optional: nur Status (default: active)
     *  - optional: dry_run=1 -> nur zählen, nichts ändern
     *
     * Umsetzung performant:
     *  - COUNT für Rückmeldung
     *  - INSERT IGNORE ... SELECT ... für Masseneintrag
     * ---------------------------------------------------------- */
    if ($action === 'auto_tag_inactive') {
        $tagId = (int)($_POST['tag_id'] ?? 0);
        if ($tagId <= 0) {
            $db->rollBack();
            jsonOut(false, 'Bitte einen gültigen Tag auswählen.', 400);
        }

        $listId = (int)($_POST['list_id'] ?? 0);
        $dryRun = (int)($_POST['dry_run'] ?? 0) === 1;

        // Default: nur aktive Empfänger taggen (kann man später optional erweitern)
        $onlyStatus = (string)($_POST['only_status'] ?? 'active');
        if ($onlyStatus !== 'active' && $onlyStatus !== '') {
            $onlyStatus = 'active';
        }

        // WHERE-Bausteine
        $where = [];
        $params = [];

        // Kernbedingung: nie geöffnet/geklickt
        $where[] = "r.last_opened_at IS NULL";
        $where[] = "r.last_clicked_at IS NULL";

        // Optional: Status
        if ($onlyStatus !== '') {
            $where[] = "r.status = ?";
            $params[] = $onlyStatus;
        }

        // Optional: Liste einschränken
        if ($listId > 0) {
            $where[] = "EXISTS (
                SELECT 1 FROM recipient_lists rl
                WHERE rl.recipient_id = r.id AND rl.list_id = ?
            )";
            $params[] = $listId;
        }

        $whereSql = "WHERE " . implode(" AND ", $where);

        // 1) COUNT wie viele Kandidaten es sind
        $countSql = "
            SELECT COUNT(*)
            FROM recipients r
            $whereSql
        ";
        $stmtCount = $db->prepare($countSql);
        $stmtCount->execute($params);
        $candidateCount = (int)$stmtCount->fetchColumn();
        ErrorLogger::logSqlSuccess('empfaenger_bulk_ajax | file: ' . __FILE__ . ' | message: COUNT auto_tag_inactive candidates=' . $candidateCount . ' | list_id=' . $listId . ' | status=' . ($onlyStatus ?: 'ALL'));

        if ($dryRun) {
            $db->commit();
            jsonOut(true, "Dry-Run: $candidateCount Empfänger würden den Tag erhalten.", 200, [
                'dry_run' => true,
                'candidates' => $candidateCount
            ]);
        }

        // 2) INSERT IGNORE ... SELECT ...
        // Hinweis: INSERT IGNORE verhindert Duplikate wegen UNIQUE(recipient_id,tag_id).
        $insertSql = "
            INSERT IGNORE INTO recipient_tags (recipient_id, tag_id)
            SELECT r.id, ?
            FROM recipients r
            $whereSql
        ";

        // tagId muss vorne in params (für SELECT r.id, ?)
        $insertParams = array_merge([$tagId], $params);

        $stmtIns = $db->prepare($insertSql);
        $stmtIns->execute($insertParams);

        // rowCount bei INSERT IGNORE kann je nach Treiber tricky sein,
        // ist aber hier als grobe Info ok:
        $inserted = (int)$stmtIns->rowCount();

        ErrorLogger::logSqlSuccess('empfaenger_bulk_ajax | file: ' . __FILE__ . ' | message: INSERT IGNORE auto_tag_inactive tag_id=' . $tagId . ' | inserted=' . $inserted . ' | candidates=' . $candidateCount);

        $db->commit();
        jsonOut(true, "Auto-Tagging abgeschlossen: candidates=$candidateCount, inserted=$inserted.", 200, [
            'candidates' => $candidateCount,
            'inserted' => $inserted
        ]);
    }

    /* ------------------------------------------------------------
     * Unbekannte Aktion
     * ---------------------------------------------------------- */
    $db->rollBack();
    jsonOut(false, 'Unbekannte Aktion: ' . $action, 400);

} catch (Throwable $e) {
    if ($db->inTransaction()) {
        $db->rollBack();
    }
    ErrorLogger::logSqlError('empfaenger_bulk_ajax | file: ' . __FILE__ . ' | error: ' . $e->getMessage());
    jsonOut(false, 'Serverfehler bei Bulk-Aktion: ' . $e->getMessage(), 500);
}
