<?php

/**
 * Performs all steps in place:
 *  - Reads schedule + round + category
 *  - Counts distinct groups
 *  - Collects each athlete's best_of_runs 
 *  - Assigns placement & final_placement
 *  - Updates runs that match origin = "round,final_placement" in the same category
 *  - Outputs JSON directly (no return)
 */
function updateNextRoundAthleteId(mysqli $conn, int $scheduleId, int $groupNumber): void 
{
	header('Content-Type: application/json; charset=utf-8'); // We set JSON header here

	// Basic validation
	if ($scheduleId < 1 || $groupNumber < 1) {
		echo json_encode([
			"success"  => false,
			"error"    => "Invalid scheduleId or groupNumber.",
			"athletes" => []
		], JSON_PRETTY_PRINT);
		return; // Stop here
	}

	// 1) Grab round + category from schedule
	$infoSql = "
		SELECT 
			h.round AS current_round,
			s.category AS schedule_category,
			s.event AS event
		FROM schedule s
		JOIN heatsystem h ON s.heatsystem = h.id
		WHERE s.id = ?
		LIMIT 1
	";
	$stmtInfo = $conn->prepare($infoSql);
	if (!$stmtInfo) {
		echo json_encode([
			"success"  => false,
			"error"    => "Failed to prepare statement for round/category: " . $conn->error,
			"athletes" => []
		], JSON_PRETTY_PRINT);
		return;
	}
	$stmtInfo->bind_param("i", $scheduleId);
	$stmtInfo->execute();
	$resInfo = $stmtInfo->get_result();
	$rowInfo = $resInfo->fetch_assoc();
	$stmtInfo->close();

	if (!$rowInfo) {
		echo json_encode([
			"success"  => false,
			"error"    => "No schedule/heatsystem data found for scheduleId=$scheduleId.",
			"athletes" => []
		], JSON_PRETTY_PRINT);
		return;
	}

	$round       = (int)$rowInfo["current_round"];
	$scheduleCat = (int)$rowInfo["schedule_category"];
	$event = (int)$rowInfo["event"]; // 'category' column of schedule

	// 2) Count how many DISTINCT groups exist for this scheduleId
	$groupsSql = "
		SELECT COUNT(DISTINCT r.`group`) AS total_groups
		FROM runs r
		WHERE r.schedule = ?
	";
	$stmtGroups = $conn->prepare($groupsSql);
	if (!$stmtGroups) {
		echo json_encode([
			"success"  => false,
			"error"    => "Failed to prepare statement for groups count: " . $conn->error,
			"athletes" => []
		], JSON_PRETTY_PRINT);
		return;
	}
	$stmtGroups->bind_param("i", $scheduleId);
	$stmtGroups->execute();
	$gcRes = $stmtGroups->get_result();
	$gcRow = $gcRes->fetch_assoc();
	$stmtGroups->close();

	$numberOfGroupsInRound = $gcRow ? (int)$gcRow["total_groups"] : 1;
	if ($numberOfGroupsInRound < 1) {
		$numberOfGroupsInRound = 1; // fallback
	}
	
	// Include the variable that holds the number of runs for the specific schedule where run = 1
	$numberOfAtheltesInRound = 0;
	$runsCountSql = "SELECT COUNT(*) AS runs_count FROM runs WHERE schedule = ? AND run = 1";
	$stmtRunsCount = $conn->prepare($runsCountSql);
	if ($stmtRunsCount) {
		$stmtRunsCount->bind_param("i", $scheduleId);
		$stmtRunsCount->execute();
		$resultRunsCount = $stmtRunsCount->get_result();
		if ($rowRunsCount = $resultRunsCount->fetch_assoc()) {
			$numberOfAtheltesInRound = (int)$rowRunsCount["runs_count"];
		}
		$stmtRunsCount->close();
	}
	
	// 3) Build an athleteMap
	$athleteMap = [];

	// Fetch runs for this schedule + group
	$runsSql = "
		SELECT 
			r.id      AS run_id,
			r.athlete AS athlete_id,
			r.status  AS run_status
		FROM runs r
		WHERE r.schedule = ?
		  AND r.`group`  = ?
	";
	$stmtRuns = $conn->prepare($runsSql);
	if (!$stmtRuns) {
		echo json_encode([
			"success"  => false,
			"error"    => "Failed to prepare runs statement: " . $conn->error,
			"athletes" => []
		], JSON_PRETTY_PRINT);
		return;
	}
	$stmtRuns->bind_param("ii", $scheduleId, $groupNumber);
	$stmtRuns->execute();
	$resRuns = $stmtRuns->get_result();

	// If no runs => respond
	if ($resRuns->num_rows === 0) {
		$stmtRuns->close();
		echo json_encode([
			"success"  => true,
			"error"    => "No runs found for schedule=$scheduleId and group=$groupNumber",
			"athletes" => []
		], JSON_PRETTY_PRINT);
		return;
	}

	// Evaluate each run => compute best_of_runs
	while ($rr = $resRuns->fetch_assoc()) {
		$runId     = (int)$rr["run_id"];
		$athleteId = (int)$rr["athlete_id"];
		$runStatus = (int)$rr["run_status"];

		if ($athleteId < 1) {
			// possibly placeholder
			continue;
		}
		if (!isset($athleteMap[$athleteId])) {
			$athleteMap[$athleteId] = [
				"best_of_runs" => 0.0,
				"dsq"          => false,
			];
		}
		// DSQ => entire athlete => dsq=true => best_of_runs=0 => skip
		if ($runStatus === 4) {
			$athleteMap[$athleteId]["dsq"] = true;
			continue;
		}
		// runStatus=2 or 3 => total_score=0 => skip
		if ($runStatus === 2 || $runStatus === 3) {
			continue;
		}

		// else => average judge scores
		$scoreQuery = "SELECT score FROM scores WHERE run = ?";
		$stmtScore  = $conn->prepare($scoreQuery);
		if (!$stmtScore) {
			// skip or partial
			continue;
		}
		$stmtScore->bind_param("i", $runId);
		$stmtScore->execute();
		$resScore = $stmtScore->get_result();

		$sum   = 0.0;
		$count = 0;
		while ($sRow = $resScore->fetch_assoc()) {
			$sum   += (float)$sRow["score"];
			$count++;
		}
		$stmtScore->close();

		$thisRunTotal = ($count > 0) ? ($sum / $count) : 0.0;
		if ($thisRunTotal > $athleteMap[$athleteId]["best_of_runs"]) {
			$athleteMap[$athleteId]["best_of_runs"] = $thisRunTotal;
		}
	}
	$stmtRuns->close();

	// 4) Build a list => sort desc
	$athList = [];
	foreach ($athleteMap as $aId => $data) {
		if ($data["dsq"]) {
			$data["best_of_runs"] = 0.0;
		}
		$athList[] = [
			"athlete_id"   => $aId,
			"best_of_runs" => (float)$data["best_of_runs"],
			"dsq"          => (bool)$data["dsq"],
		];
	}
	usort($athList, function($a, $b) {
		return $b["best_of_runs"] <=> $a["best_of_runs"];
	});

	// 5) Assign placements
	$rank = 1;
	foreach ($athList as &$ath) {
		if ($ath["dsq"]) {
			$ath["placement"]       = 0;
			$ath["final_placement"] = 0;
		} else {
			$ath["placement"] = $rank;
			$fp = ($numberOfGroupsInRound * $rank) - $groupNumber + 1;
			
			if($fp > $numberOfAtheltesInRound)
			{
				$fp = $numberOfAtheltesInRound;
			}
			$ath["final_placement"] = $fp;
			$rank++;
		}
	}
	unset($ath);

	// 6) For each athlete => if final_placement>0 => update runs 
	//    with origin="$round,$final_placement" in same category
	foreach ($athList as $ath) {
		if ($ath["final_placement"] > 0) {
			$originStr = $round . "," . $ath["final_placement"];
			$updQuery = "
				UPDATE runs r
				JOIN schedule s ON r.schedule = s.id
				SET r.athlete = ?
				WHERE r.origin = ?
				  AND s.category = ?
				  AND s.event = ?
			";
			$updStmt  = $conn->prepare($updQuery);
			if ($updStmt) {
				$updStmt->bind_param("isii",
					$ath["athlete_id"],
					$originStr,
					$scheduleCat,
					$event
				);
				$updStmt->execute();
				$updStmt->close();
			}
		}
	}

	// 7) now only echo JSON with athlete_id, round, final_placement
	$finalOutput = [];
	foreach ($athList as $ath) {
		$finalOutput[] = [
			"athlete_id"      => $ath["athlete_id"],
			"round"           => $round,
			"final_placement" => $ath["final_placement"],
		];
	}

	echo json_encode([
		"success"  => true,
		"error"    => null,
		"athletes" => $finalOutput,
	], JSON_PRETTY_PRINT);
}

// 2) Example usage of the function
// Let's say we have 12 athletes, max 4 per group, 3 groups, round 2, etc.:
include('dbconnect.php');
$schedule_id = $_GET['schedule'];
$groupNumber = $_GET['groupNumber'];

// Call the function
$result = updateNextRoundAthleteId(
	$conn,
	$schedule_id,
	$groupNumber
);

?>

?>