<?php
ini_set("display_errors",1);
header('Content-Type: application/json');

if (!isset($baseDir)) {
	$baseDir = $_SERVER['DOCUMENT_ROOT'];
}

require_once $baseDir . '/../scripts/session_functions.php';

ini_wkvs_session();

check_user_permission('wk_leitung');

verify_csrf();

require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';

require $baseDir . '/../scripts/string-calculator/string-calculator-functions.php';


$type = 'wkl';
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';

if ($dbconnection['success'] !== true){
    echo json_encode(['success' => false, 'message' => 'Critical DB Error.']);
    exit;
}

require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-display-dependencies-cache.php';
require_once $baseDir . '/../scripts/cache/cache-creators/regenerate-noten-cache.php';



$recalculateJSONs = false;

$action = $_POST['action'] ?? '';

if ($action === 'add') {
    $name = trim($_POST['name'] ?? '');
    $type_val = $_POST['type_val'] ?? 'input';
    $berechnung = trim($_POST['berechnung'] ?? '');
    $pro_geraet = intval($_POST['pro_geraet'] ?? 0);
    $default_value = (isset($_POST['default_value'])) ? floatval($_POST['default_value']) : null;
    $min_value = (isset($_POST['min_value'])) ? floatval($_POST['min_value']) : null;
    $max_value = (isset($_POST['max_value'])) ? floatval($_POST['max_value']) : null;

    $id = (isset($_POST['id'])) ? floatval($_POST['id']) : 1;

    if (!$id) {
        echo json_encode(['success' => false, 'message' => 'Id ist erforderlich.']);
        exit;
    }

    $stmt = $mysqli->prepare("SELECT 1 FROM $db_tabelle_wertungstypen WHERE id = ?");
    $stmt->bind_param("i", $id);
    $stmt->execute();

    $result = $stmt->get_result();

    if ($result->num_rows > 0) {
        echo json_encode([
            'success' => false,
            'message' => 'Eine Note mit dieser Id existiert bereits.'
        ]);
        $stmt->close();
        exit;
    }

    $stmt->close();


    if (!$name) {
        echo json_encode(['success' => false, 'message' => 'Name ist erforderlich.']);
        exit;
    }

    $stmt = $mysqli->prepare("INSERT INTO $db_tabelle_wertungstypen (id, name, type, berechnung, pro_geraet, default_value, min_value, max_value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
    $stmt->bind_param("isssisss", $id, $name, $type_val, $berechnung, $pro_geraet, $default_value, $min_value, $max_value);
    $success = $stmt->execute();
    $new_id = $mysqli->insert_id;
    $stmt->close();

    $recalculateJSONs = true;

    if ($success) {
        regenerate_noten_cache($mysqli, $db_tabelle_wertungstypen, $baseDir);
        generateIntersectCache($mysqli, $baseDir);
        if (!$recalculateJSONs) { echo json_encode(['success' => true, 'id' => $new_id]); }
    } else {
        echo json_encode(['success' => false, 'message' => 'Fehler beim Hinzufügen.']);
        exit;
    }

} elseif ($action === 'update') {
    $id = intval($_POST['id'] ?? 0);
    $field = $_POST['field'] ?? '';
    $value = $_POST['value'] ?? '';

    $allowedFields = ['name', 'type', 'berechnung', 'pro_geraet', 'geraete_json', 'anzahl_laeufe_json', 'default_value', 'min_value', 'max_value', 'zeige_auf_rangliste', 'nullstellen', 'display_string', 'groesse_auf_rangliste'];
    if ($id > 0 && in_array($field, $allowedFields)) {
        if ($field === 'pro_geraet') {
            $value = intval($value);
        }

        if ($field === 'berechnung' || $field === 'type') {
            $recalculateJSONs = true;
        }
        
        $updated = db_update($mysqli, $db_tabelle_wertungstypen, [$field => $value], ['id' => $id]);
        if ($updated !== false) {
            regenerate_noten_cache($mysqli, $db_tabelle_wertungstypen, $baseDir);
            generateIntersectCache($mysqli, $baseDir);
            if (!$recalculateJSONs) { echo json_encode(['success' => true]); }
        } else {
            echo json_encode(['success' => false, 'message' => 'DB Update failed.']);
            exit;
        }
    } else {
        echo json_encode(['success' => false, 'message' => 'Invalid parameters.']);
        exit;
    }

} elseif ($action === 'delete') {
    $id = intval($_POST['id'] ?? 0);

    if ($id > 0) {
        db_delete($mysqli, $db_tabelle_wertungstypen, ['id' => $id]);
        regenerate_noten_cache($mysqli, $db_tabelle_wertungstypen, $baseDir);
        generateIntersectCache($mysqli, $baseDir);
        echo json_encode(['success' => true]);
    } else {
        echo json_encode(['success' => false, 'message' => 'Invalid ID.']);
    }

} else {
    echo json_encode(['success' => false, 'message' => 'Action not found.']);
    exit;
}

if ($recalculateJSONs) {
    $noten = db_select($mysqli, $db_tabelle_wertungstypen, "id, berechnung, type");

    // 1. Re-index the array so the keys match the database IDs
    $notenById = array_column($noten, null, 'id');

    $berechnungen = [];
    foreach ($notenById as $id => $sn) {
        if ($sn['type'] === 'berechnung') {
            $berechnungen[] = $sn;
        }
    }

    if (empty($berechnungen)) {
        echo json_encode(['success' => true, 'message' => "Keine Berechnungen ausgewählt"]);
        exit;
    }

    $notenRechner = new NotenRechner();

    // 1. Build the direct map
    // Format: [ Changed_Note_ID => [ "CalcId|GeraetId" => [CalcId, GeraetId] ] ]
    $dependencyMap = [];

    foreach ($berechnungen as $calc) {
        $neededIdsArrayWithRun = $notenRechner->getBenoetigteIdsComplexWithRun($calc['berechnung']);
        
        if (empty($neededIdsArrayWithRun) || count($neededIdsArrayWithRun) < 2) { 
            continue; 
        }

        $calcId = (int)$calc['id'];

        $neededIdsArray = $neededIdsArrayWithRun;

        unset($neededIdsArray['targetRun']);
        unset($neededIdsArray['targetGeraet']);

        $targetRunId = $neededIdsArrayWithRun['targetRun'];
        $target_geraet_id = $neededIdsArrayWithRun['targetGeraet'];

        foreach ($neededIdsArray as $key => $needed) {

            $nId = (int)$needed['noteId'];
            
            // Keep geraetId as integer if it's a number (e.g., 3), otherwise string ('S')
            $gId = is_numeric($needed['geraetId']) ? (int)$needed['geraetId'] : $needed['geraetId'];
            
            // Create a unique string key so we don't store exact duplicates
            $nodeKey = $calcId . '|' . $gId . '|' . $targetRunId . '|' . $target_geraet_id; // e.g., "10|S|R2" or "12|3|RA"
            
            if (!isset($dependencyMap[$nId])) {
                $dependencyMap[$nId] = [];
            }
            
            // Store it as the "little array" you requested: [DependentCalcId, GeraetId]
            $dependencyMap[$nId][$nodeKey] = [$calcId, $gId, [$targetRunId, $target_geraet_id]];
        }
    }


    // 2. Our recursive helper function (Updated for complex nodes)
    function getCompleteDependencyChain($id, $directMap, $visited = []) 
    {
        // If this ID doesn't have anything depending on it, return empty
        if (!isset($directMap[$id])) {
            return [];
        }

        $allDependencies = [];

        foreach ($directMap[$id] as $nodeKey => $complexNode) {
            // CIRCULAR DEPENDENCY CHECK:
            // We check against the string key (e.g., "10|S") to prevent infinite loops
            if (isset($visited[$nodeKey])) {
                continue;
            }

            // 1. Mark this specific node as visited
            $visited[$nodeKey] = true;

            // 2. Add the little array [CalcId, GeraetId] to our master list
            $allDependencies[$nodeKey] = $complexNode;

            // 3. Recursively find everything that depends on THIS calculation ID
            // $complexNode[0] is the dependent Calc ID
            $childDependencies = getCompleteDependencyChain($complexNode[0], $directMap, $visited);
            
            // 4. Merge the child results into our master list safely
            foreach ($childDependencies as $childKey => $childNode) {
                $allDependencies[$childKey] = $childNode;
                $visited[$childKey] = true; // Ensure the parent loop knows this was visited
            }
        }

        return $allDependencies;
    }


    // 3. Create the final flattened map for ALL IDs
    $flatDependencyMap = [];

    foreach (array_keys($notenById) as $id) {
        $chain = getCompleteDependencyChain($id, $dependencyMap);
        
        // Only add it if dependencies exist
        if (!empty($chain)) {
            // array_values() removes the "10|S" string keys, turning it into a perfect 
            // 0-indexed array for clean JSON encoding: [[10, "S"], [12, 3]]
            $flatDependencyMap[$id] = array_values($chain);
        }
    }


    // 4. Database Updates
    // Step 1: Reset all rows to NULL in a single query
    $resetSql = "UPDATE $db_tabelle_wertungstypen SET `berechnung_json` = NULL";
    $mysqli->query($resetSql);

    // Step 2: Prepare the statement
    $updateSql = "UPDATE $db_tabelle_wertungstypen SET `berechnung_json` = ? WHERE id = ?";
    $stmt = $mysqli->prepare($updateSql);

    foreach ($flatDependencyMap as $id => $completeDependencyArray) {
        if (empty($completeDependencyArray)) {
            continue;
        }

        $jsonString = json_encode($completeDependencyArray);
        
        // Bind parameters: 's' for string (JSON), 'i' for integer (ID)
        $stmt->bind_param("si", $jsonString, $id);
        $stmt->execute();
    }

    $stmt->close();

    echo json_encode(['success' => true, 'message' => "Abhaengigkeiten berechnet"]);
    exit;
}