<?php
// =============================================================
//  POST /api/v1/assessments/nurse_submit
//
//  Submits ONE stage of a nurse's 3-stage assessment — mirrors
//  app/nurse_assessment_form.php's POST handler field-for-field (same 21
//  criteria, same scoring/grading/final-verdict math, same INSERT-only-at-
//  stage-1 vs UPDATE-otherwise branching), rather than re-deriving it.
//
//  The stage is NEVER taken from the client — it's derived from the
//  caller's own user_type, exactly like the web form's
//  $allowed_stage/$requested_stage check, so a client can't submit a
//  stage it doesn't hold the role for.
//
//  Body: {
//    "nurse_id": 53, "rotation_id": 52, "schedule_id": 1255,
//    "scores": { "a1_history_physical": 5, ... all 21 keys ... },
//    "comments": "optional text"
//  }
// =============================================================

require_once __DIR__ . '/../_bootstrap.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    Api::error(405, 'MethodNotAllowed', 'Use POST');
}

$account = api_authenticate();

$userType = $account->getUserType();
if ($userType === 'In_Charge') {
    $stage = 1;
} elseif ($userType === 'Nurse_Manager') {
    $stage = 2;
} elseif (in_array($userType, ['Chief_Preceptor', 'Preceptor'], true)) {
    $stage = 3;
} else {
    Api::error(403, 'Forbidden', 'Your role does not assess at any stage of the nurse pipeline.');
}
$prefix = "s{$stage}_";

// See nurse_pending.php's matching comment — Nurse_Manager holds
// 'assess_nurses_stage2' but not the generic 'assess_students'.
api_require_any_permission(['assess_students', "assess_nurses_stage{$stage}"]);

$body       = json_decode(file_get_contents('php://input'), true) ?? [];
$nurseId    = (int)($body['nurse_id'] ?? 0);
$rotationId = (int)($body['rotation_id'] ?? 0);
$scheduleId = (int)($body['schedule_id'] ?? 0);
$comments   = trim((string)($body['comments'] ?? ''));
$scoresIn   = is_array($body['scores'] ?? null) ? $body['scores'] : [];

if (!$nurseId || !$rotationId || !$scheduleId) {
    Api::error(422, 'ValidationError', 'nurse_id, rotation_id, and schedule_id are required');
}

// Same 21 criteria, same order, as app/nurse_assessment_form.php.
$allFields = [
    'a1_history_physical', 'a2_care_plan', 'a3_clinical_decisions', 'a4_documentation', 'a5_counseling',
    'b1_appearance', 'b2_nurse_patient_relation', 'b3_team_relationship', 'b4_responsibility',
    'b5_communication', 'b6_standards_protocols',
    'c1_procedures', 'c2_equipment_use', 'c3_equipment_maintenance', 'c4_hospital_economy',
    'd1_punctuality', 'd2_clinical_meeting', 'd3_conference', 'd4_ward_rounds',
    'e1_teach_supervise', 'e2_innovation',
];

$scores = [];
$totalScore = 0;
$maxPossible = count($allFields) * 5; // 105
foreach ($allFields as $field) {
    $val = min(5, max(0, (int)($scoresIn[$field] ?? 0)));
    $scores[$field] = $val;
    $totalScore += $val;
}
$pct = $maxPossible > 0 ? round(($totalScore / $maxPossible) * 100, 2) : 0;
$grade = gradeFor($pct);

// ── Fetch nurse + schedule (also confirms it's a real, matching triple) ────
$infoStmt = $conn->prepare("
    SELECT rn.id, nrs.unit_id, nrs.unit_name, nrs.department_id, nrs.department_name
    FROM rotation_nurses rn
    JOIN nurse_rotations nr ON nr.nurse_id = rn.id
    JOIN nurse_rotation_schedules nrs ON nrs.nurse_rotation_id = nr.id
    WHERE rn.id = ? AND nrs.id = ? AND nr.id = ?
    LIMIT 1
");
$infoStmt->bind_param('iii', $nurseId, $scheduleId, $rotationId);
$infoStmt->execute();
$nurse = $infoStmt->get_result()->fetch_assoc();
$infoStmt->close();
if (!$nurse) {
    Api::error(404, 'NotFound', 'No matching nurse/rotation/schedule record found.');
}

// ── Existing assessment row + gates (mirrors the form's pipeline guards) ───
$asmtStmt = $conn->prepare('SELECT * FROM nurse_assessments WHERE rotation_nurse_id = ? AND nurse_rotation_id = ? AND nurse_rotation_schedule_id = ?');
$asmtStmt->bind_param('iii', $nurseId, $rotationId, $scheduleId);
$asmtStmt->execute();
$existing = $asmtStmt->get_result()->fetch_assoc();
$asmtStmt->close();

if ($stage === 1) {
    $lesStmt = $conn->prepare("SELECT id FROM nurse_lessons WHERE rotation_nurse_id = ? AND nurse_rotation_schedule_id = ? AND status = 'submitted' LIMIT 1");
    $lesStmt->bind_param('ii', $nurseId, $scheduleId);
    $lesStmt->execute();
    $lessonOk = (bool)$lesStmt->get_result()->fetch_assoc();
    $lesStmt->close();
    if (!$lessonOk) {
        Api::error(409, 'LessonsNotSubmitted', 'This nurse has not yet submitted their lessons learned for this unit.');
    }
}
if ($stage === 2 && (!$existing || ($existing['stage1_status'] ?? 'pending') !== 'submitted')) {
    Api::error(409, 'PreviousStagePending', 'Stage 1 must be submitted before Stage 2.');
}
if ($stage === 3 && (!$existing || ($existing['stage2_status'] ?? 'pending') !== 'submitted')) {
    Api::error(409, 'PreviousStagePending', 'Stage 2 must be submitted before Stage 3.');
}
$stageStatusKey = "stage{$stage}_status";
if ($existing && in_array($existing[$stageStatusKey] ?? '', ['submitted', 'locked'], true)) {
    Api::error(409, 'AlreadySubmitted', "Stage {$stage} has already been submitted for this nurse.");
}

$newOverall = $stage === 1 ? 'stage2_pending' : ($stage === 2 ? 'stage3_pending' : 'completed');

$finalPct = $finalGrade = $finalVerdict = null;
if ($stage === 3 && $existing) {
    $avg = (((float)($existing['s1_percentage'] ?? 0)) + ((float)($existing['s2_percentage'] ?? 0)) + $pct) / 3;
    $finalPct = round($avg, 2);
    $finalGrade = gradeFor($finalPct);
    $finalVerdict = $finalPct >= 50 ? 'Pass' : 'Fail';
}

$assessorId = $account->getId();
$assessorName = $account->getFirstname() . ' ' . $account->getSurname();
$assessorRank = $account->getDesignation() ?? '';

if ($existing) {
    $setParts = [];
    $setParams = [];
    $setTypes = '';
    foreach ($scores as $f => $v) {
        $setParts[] = "{$prefix}{$f} = ?";
        $setParams[] = $v;
        $setTypes .= 'i';
    }
    $setParts = array_merge($setParts, [
        "{$prefix}total_score = ?", "{$prefix}max_possible = ?", "{$prefix}percentage = ?", "{$prefix}grade = ?",
        "stage{$stage}_assessor_id = ?", "stage{$stage}_assessor_name = ?", "stage{$stage}_assessor_rank = ?",
        "stage{$stage}_comments = ?", "stage{$stage}_status = 'submitted'", "stage{$stage}_submitted_at = NOW()",
        "overall_status = ?",
    ]);
    array_push($setParams, $totalScore, $maxPossible, $pct, $grade, $assessorId, $assessorName, $assessorRank, $comments, $newOverall);
    $setTypes .= 'iidsisss' . 's';

    if ($stage === 3 && $finalPct !== null) {
        $setParts[] = 'final_percentage = ?';
        $setParts[] = 'final_grade = ?';
        $setParts[] = 'final_verdict = ?';
        array_push($setParams, $finalPct, $finalGrade, $finalVerdict);
        $setTypes .= 'dss';
    }

    $setParams[] = $existing['id'];
    $setTypes .= 'i';

    $sql = 'UPDATE nurse_assessments SET ' . implode(', ', $setParts) . ' WHERE id = ?';
    $stmt = $conn->prepare($sql);
    $stmt->bind_param($setTypes, ...$setParams);
} else {
    $cols = [
        'rotation_nurse_id', 'nurse_rotation_id', 'nurse_rotation_schedule_id',
        'unit_id', 'unit_name', 'department_id', 'department_name',
        "{$prefix}total_score", "{$prefix}max_possible", "{$prefix}percentage", "{$prefix}grade",
        "stage{$stage}_assessor_id", "stage{$stage}_assessor_name", "stage{$stage}_assessor_rank",
        "stage{$stage}_comments", "stage{$stage}_status", "stage{$stage}_submitted_at",
        'overall_status', 'created_by',
    ];
    $vals = [
        $nurseId, $rotationId, $scheduleId,
        $nurse['unit_id'], $nurse['unit_name'], $nurse['department_id'], $nurse['department_name'],
        $totalScore, $maxPossible, $pct, $grade,
        $assessorId, $assessorName, $assessorRank,
        $comments, 'submitted', date('Y-m-d H:i:s'),
        $newOverall, $assessorId,
    ];
    $typesArr = ['i', 'i', 'i', 'i', 's', 'i', 's', 'i', 'i', 'd', 's', 'i', 's', 's', 's', 's', 's', 's', 'i'];
    foreach ($scores as $f => $v) {
        $cols[] = "{$prefix}{$f}";
        $vals[] = $v;
        $typesArr[] = 'i';
    }
    $ph = implode(',', array_fill(0, count($vals), '?'));
    $sql = 'INSERT INTO nurse_assessments (' . implode(',', $cols) . ") VALUES ($ph)";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param(implode('', $typesArr), ...$vals);
}

if (!$stmt->execute()) {
    Api::error(500, 'ServerError', 'Could not save the assessment. Please try again.');
}
$stmt->close();

Api::success([
    'stage'          => $stage,
    'total_score'    => $totalScore,
    'max_possible'   => $maxPossible,
    'percentage'     => $pct,
    'grade'          => $grade,
    'final_percentage' => $finalPct,
    'final_grade'      => $finalGrade,
    'final_verdict'    => $finalVerdict,
]);

/** Same percentage-to-grade thresholds as the web form. */
function gradeFor(float $pct): string
{
    if ($pct >= 80) return 'Excellent';
    if ($pct >= 65) return 'Very Good';
    if ($pct >= 50) return 'Good';
    if ($pct >= 35) return 'Fair';
    return 'Poor';
}
