<?php

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

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

ini_wkvs_session();

check_user_permission('kampfrichter');

verify_csrf();

$type = 'kr';

$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';

if ($data['success'] === false){
	echo json_encode(['success' => false, 'message' => $data['message']]);
    exit; 
}

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

$person_id  = isset($_POST['personId']) ? intval($_POST['personId']) : 0;
$field_type_id = intval($_POST['fieldTypeId'] ?? 0);
$gereat_id     = intval($_POST['gereatId'] ?? 0);
$jahr       = isset($_POST['jahr']) ? intval($_POST['jahr']) : 0;
$run_number = isset($_POST['run']) ? intval($_POST['run']) : 1;

if (!isset($_POST['value'])) {
    echo json_encode(['success' => false, 'message' => 'Kein Value angegeben']);
    exit;
}

$valueNoteUpdate = floatval($_POST['value']);

if ($person_id < 1) {
    echo json_encode(['success' => false, 'message' => 'Invalide Personen-ID']);
    exit;
}

if ($jahr < 1) {
    echo json_encode(['success' => false, 'message' => 'Invalides Jahr']);
    exit;
}

if ($gereat_id < 1) {
    echo json_encode(['success' => false, 'message' => 'Invalide Geraet-ID']);
    exit;
}

$geratExistiert = db_get_var($mysqli, "SELECT 1 FROM $db_tabelle_disziplinen WHERE id = ? LIMIT 1", [$gereat_id]);

if (!$geratExistiert) {
    echo json_encode(['success' => false, 'message' => 'Invalide Geraet-ID']);
    exit;
}

if ($field_type_id < 1) {
    echo json_encode(['success' => false, 'message' => 'Invalide Notentyp-ID']);
    exit;
}

$noteConfig = db_select($mysqli, $db_tabelle_wertungstypen, "*", "id = ?", [$field_type_id]);

if (count($noteConfig) !== 1) {
    echo json_encode(['success' => false, 'message' => 'Invalide Notentyp-ID']);
    exit;
}

$singleNoteConfig = $noteConfig[0];

if ($singleNoteConfig['max_value'] !== null && $valueNoteUpdate > $singleNoteConfig['max_value']) {
    echo json_encode(['success' => false, 'message' => "Wert zu hoch (max " . $singleNoteConfig['max_value'].")"]);
    exit;
}

if ($singleNoteConfig['min_value'] !== null && $valueNoteUpdate < $singleNoteConfig['min_value']){
    echo json_encode(['success' => false, 'message' => "Wert zu niedrig (min " . $singleNoteConfig['min_value'].")"]);
    exit;
}

$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;

$oldNote = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_wertungen WHERE `person_id` = ? AND `note_bezeichnung_id` = ? AND `geraet_id` = ? AND `wk_id` = ? AND `run_number` = ?", [$person_id, $field_type_id, $gereat_id, $current_wk_id, $run_number]);  

$sql = "INSERT INTO $db_tabelle_wertungen (`value`, `person_id`, `note_bezeichnung_id`, `geraet_id`, `wk_id`, `run_number`) 
        VALUES (?, ?, ?, ?, ?, ?) 
        ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)";

$stmt = $mysqli->prepare($sql);

$stmt->bind_param("siiiii", $valueNoteUpdate, $person_id, $field_type_id, $gereat_id, $current_wk_id, $run_number);

$stmt->execute();

$stmt->close();

$userId = (int) $_SESSION['user_id_kampfrichter'];

$sql = "INSERT INTO $db_tabelle_wertungen_log (`new_value`, `old_value`, `person_id`, `note_bezeichnung_id`, `geraet_id`, `wk_id`, `run_number`, `edited_by`) 
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)";

$stmt = $mysqli->prepare($sql);

$stmt->bind_param("ssiiiiii", $valueNoteUpdate, $oldNote, $person_id, $field_type_id, $gereat_id, $current_wk_id, $run_number, $userId);

$stmt->execute();

$stmt->close();

if ($singleNoteConfig['berechnung_json'] === null) {
    echo json_encode(['success' => true, 'message' => "Wert aktualisiert"]);
    exit;
}

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

$updateNoten = [];

$notenRechner = new NotenRechner();

try {
    $abhaenigeRechnungen = json_decode($singleNoteConfig['berechnung_json']);
} catch (Exception $e) {
    echo json_encode(['success' => true, 'message' => "Wert aktualisiert, fehler bei der Berechnung der weiteren Werte"]);
    exit;
}

$geraete = db_select($mysqli, $db_tabelle_disziplinen, "id");

$programmName = db_get_var($mysqli, "SELECT `programm` FROM $db_tabelle_teilnehmende WHERE `id` = ?", [$person_id]);

$programmId = db_get_var($mysqli, "SELECT `id` FROM $db_tabelle_kategorien WHERE `programm` = ?", [$programmName]);

// We load the configuration native cached array
$cache = require $baseDir . '/../scripts/cache/noten-config-calculating-cache.php';

$noten = db_select($mysqli, $db_tabelle_wertungen, "`value`, `note_bezeichnung_id`, `geraet_id`, `run_number`", "`person_id` = ? AND `wk_id` = ? AND `value` IS NOT NULL", [$person_id, $current_wk_id]);

$ascArrayDefaultValues    = $cache['default_values'];
$ascArrayProGeraet        = $cache['pro_geraet'];
$ascArrayGeraeteJSON      = $cache['geraete_json'];
$ascArrayAnzahlLaeufeJSON = $cache['anzahl_laeufe_json'];
$ascArrayRechnungen       = $cache['rechnungen'];
$indexedNullstellen       = $cache['nullstellen'];

$mRunFunctions = [];

foreach ($abhaenigeRechnungen as $saRechnung) {
    $sRechnung = $ascArrayRechnungen[$saRechnung[0]] ?? 0;
    //var_dump($sRechnung);
    $mRunCalc = $notenRechner->checkRunFunctions($sRechnung) ?? false;

    if ($mRunCalc) {
        $mRunFunctions[] = $saRechnung[0];
    }
}

$indexedNotenArray = [];

foreach ($geraete as $g) {
    $indexedNotenArray[$g['id']] = [];
}

$indexedNotenArray[0] = [];

foreach ($noten as $sn) {
    $indexedNotenArray[$sn['geraet_id']][$sn['note_bezeichnung_id']][$sn['run_number']] = ["value" => $sn['value'], "type" => "note"];
}

$requiredNoteIds = [];
$requiredNoteIds[$field_type_id] = true;

foreach ($abhaenigeRechnungen as $saRechnung) {
    // Only load dependencies for the specifically connected calculations
    $sRechnungStr = $ascArrayRechnungen[$saRechnung[0]] ?? '';
    if ($sRechnungStr !== '') {
         $ids = $notenRechner->getBenoetigteIdsComplex($sRechnungStr);
         foreach ($ids as $idConfig) {
             $requiredNoteIds[(int)$idConfig['noteId']] = true;
         }
    }
}
$alleNotenIds = array_keys($requiredNoteIds);

if (count($mRunFunctions) > 0) {
    foreach ($indexedNotenArray as $sG => $siNA) {
        foreach ($alleNotenIds as $neni) { 
            if (!isset($ascArrayDefaultValues[$neni])) continue; 
            
            $isProGeraet = (int)($ascArrayProGeraet[$neni] ?? 0);
            if ($isProGeraet === 1 && (int)$sG === 0) continue; 

            if ($isProGeraet !== 1) {
                $allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
                if (!is_array($allowedGeraete) || !in_array($sG, $allowedGeraete)) continue;
            }

            $runs = $ascArrayAnzahlLaeufeJSON[$neni][$sG][$programmId] ?? $ascArrayAnzahlLaeufeJSON[$neni][$sG]['all'] ?? $ascArrayAnzahlLaeufeJSON[$neni]["default"] ?? 1;

            for ($r = 1; $r <= $runs; $r++) {
                if (!isset($indexedNotenArray[$sG][$neni][$r])) { 
                    $indexedNotenArray[$sG][$neni][$r] = ["value" => $ascArrayDefaultValues[$neni], "type" => "default_value"];
                }
            }
        }
    }
} else {
    foreach ($indexedNotenArray as $sG => $siNA) {
        foreach ($alleNotenIds as $neni) { 
            if (isset($indexedNotenArray[$sG][$neni][$run_number])) continue; 
            if (!isset($ascArrayDefaultValues[$neni])) continue; 

            $isProGeraet = (int)($ascArrayProGeraet[$neni] ?? 0);
            if ($isProGeraet === 1 && (int)$sG === 0) continue; 

            if ($isProGeraet !== 1) {
                $allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
                if (!is_array($allowedGeraete) || !in_array($sG, $allowedGeraete)) continue;
            }

            $indexedNotenArray[$sG][$neni][$run_number] = ["value" => $ascArrayDefaultValues[$neni], "type" => "default_value"];
        }
    }
}

// We only want to save the IDs that were actually recalculated
$idsToSave = []; 

foreach ($abhaenigeRechnungen as $sRechnung) {
    $targetNoteId = $sRechnung[0];
    $rechnungType = $sRechnung[1];
    $targetRun = $sRechnung[2][0] ?? 'A';

    // 1. Initial Filter
    if ($rechnungType !== "A" && intval($rechnungType) !== $gereat_id) continue;

    $rechnung = $ascArrayRechnungen[$targetNoteId] ?? null;
    if ($rechnung === null) {
        echo json_encode(['success' => true, 'message' => "Fehler: Rechnung $targetNoteId nicht gefunden"]);
        exit;
    }

    // 2. Determine Target Device ID
    $isProGeraet = (intval($ascArrayProGeraet[$targetNoteId] ?? 0) === 1);
    $allowedGeraete = $ascArrayGeraeteJSON[$targetNoteId] ?? [];

    if ($rechnungType === "A" || $isProGeraet || in_array($gereat_id, $allowedGeraete)) {
        $targetGeraetKey = $gereat_id;
    } else {
        $targetGeraetKey = 0;
    }

    // 3. Calculation Logic
    $runsConfig = $ascArrayAnzahlLaeufeJSON[$targetNoteId] ?? [];
    $runs = $runsConfig[$targetGeraetKey][$programmId] ?? $runsConfig[$targetGeraetKey]["all"] ?? $runsConfig["default"] ?? 1;

    $acrun = min($runs, $run_number);

    if (in_array($targetNoteId, $mRunFunctions)) {
        $calcResult = $notenRechner->berechneStringComplexRun($rechnung, $indexedNotenArray, $targetGeraetKey, $programmId, $ascArrayAnzahlLaeufeJSON);
    } else {
        $calcResult = $notenRechner->berechneStringComplex($rechnung, $indexedNotenArray, $targetGeraetKey, $acrun);
    }

    if (!($calcResult['success'] ?? false)) {
        echo json_encode(['success' => true, 'message' => "Rechenfehler in $targetNoteId: " . ($calcResult['value'] ?? '')]);
        exit;
    }

    $acTargetRun = ($targetRun === "A") ? $acrun : intval($targetRun);
    

    // 4. Update State
    $val = $calcResult['value'];
    $indexedNotenArray[$targetGeraetKey][$targetNoteId][$acTargetRun] = ["value" => $val, "type" => "berechnet"];
    $updatedValues[$targetGeraetKey][$targetNoteId][$acTargetRun] = $val;
}

// Prepare the statement once
$sql = "INSERT INTO $db_tabelle_wertungen (`value`, `person_id`, `note_bezeichnung_id`, `geraet_id`, `wk_id`, `run_number`) 
        VALUES (?, ?, ?, ?, ?, ?)
        ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)";

$stmt = $mysqli->prepare($sql);
$formatedNoten = [];

$mysqli->begin_transaction();

foreach ($updatedValues as $gereat => $notenArray) {
    foreach ($notenArray as $note => $runArray) {
        foreach ($runArray as $run => $value) {
            $stmt->bind_param("siiiii", $value, $person_id, $note, $gereat, $current_wk_id, $run);
            $stmt->execute();
            $formatedNoten[$gereat][$note][$run] = number_format($value ,$indexedNullstellen[$note] ?? 2);
        }
    }
}

$mysqli->commit();

$formatedNoten[$gereat_id][$field_type_id][$run_number] = number_format($valueNoteUpdate ,$indexedNullstellen[$field_type_id] ?? 2);

$stmt->close();
$mysqli->close();

echo json_encode([
    'success' => true, 
    'message' => "Wert aktualisiert, alle Berechnungen durchgeführt", 
    "noten"   => $formatedNoten
]);