<?php
require_once '../../../config.php';
require_once __DIR__ . '/../../../lib/academic_period.php';
$conn = getDBConnection();

// Ensure attendance_total_days column exists (idempotent)
$conn->query("ALTER TABLE report_details ADD COLUMN IF NOT EXISTS attendance_total_days INT NOT NULL DEFAULT 0");
$conn->query("ALTER TABLE report_details ADD COLUMN IF NOT EXISTS headteacher_remark TEXT NULL DEFAULT NULL");

// Set header to return JSON
header('Content-Type: application/json');

// Enable error reporting for debugging (remove in production)
error_reporting(E_ALL);
ini_set('display_errors', 1);

$response = ['success' => false, 'message' => ''];

// Get JSON data
$input = file_get_contents('php://input');
if (!$input) {
    $response['message'] = 'No data received';
    echo json_encode($response);
    exit;
}

$data = json_decode($input, true);
if (json_last_error() !== JSON_ERROR_NONE) {
    $response['message'] = 'Invalid JSON: ' . json_last_error_msg();
    echo json_encode($response);
    exit;
}

if (!$data) {
    $response['message'] = 'Invalid data format';
    echo json_encode($response);
    exit;
}

$student_id = intval($data['student_id'] ?? 0);
$term = $data['term'] ?? '';
$academic_year = $data['academic_year'] ?? '';
$fields = $data['fields'] ?? [];
$signatures = $data['signatures'] ?? [];
$scores = $data['scores'] ?? [];

// Validate required fields
if (!$student_id || !$term || !$academic_year) {
    $response['message'] = 'Missing required fields';
    echo json_encode($response);
    exit;
}

// Begin transaction
$conn->begin_transaction();

try {
    // Process signatures — empty string means "no new signature drawn, keep existing"
    $director_signature    = saveSignatureImage($signatures['director']    ?? '', 'director',    $student_id, $term);
    $headteacher_signature = saveSignatureImage($signatures['headteacher'] ?? '', 'headteacher', $student_id, $term);
    $classteacher_signature = saveSignatureImage($signatures['classteacher'] ?? '', 'classteacher', $student_id, $term);

    // Check if report details exist
    $check_stmt = $conn->prepare("SELECT id, director_signature, headteacher_signature, class_teacher_signature FROM report_details WHERE student_id = ? AND term = ? AND academic_year = ?");
    $check_stmt->bind_param("iss", $student_id, $term, $academic_year);
    $check_stmt->execute();
    $result     = $check_stmt->get_result();
    $existingRow = $result->fetch_assoc();
    $exists      = $existingRow !== null;
    $check_stmt->close();

    // Preserve existing signatures if no new one was drawn
    if (empty($director_signature)     && $exists) $director_signature    = $existingRow['director_signature']       ?? '';
    if (empty($headteacher_signature)  && $exists) $headteacher_signature = $existingRow['headteacher_signature']    ?? '';
    if (empty($classteacher_signature) && $exists) $classteacher_signature = $existingRow['class_teacher_signature'] ?? '';

    // Prepare field values with defaults
    $attendance_out_of = isset($fields['attendance_out_of']) ? intval($fields['attendance_out_of']) : 0;

    // If 'attendance' field exists, use it for attendance_out_of
    if (isset($fields['attendance']) && !empty($fields['attendance'])) {
        $attendance_out_of = intval($fields['attendance']);
    }

    // Total school days — from calendar if available, else from posted value
    $attendance_total_days = isset($fields['attendance_total_days']) ? intval($fields['attendance_total_days']) : 0;
    if ($attendance_total_days <= 0) {
        $attendance_total_days = getTermSchoolDays($conn, $academic_year, $term, 0);
    }
    
    $promoted_to = $fields['promoted_to'] ?? '';
    $conduct = $fields['conduct'] ?? 'SATISFACTORY';
    $interest = $fields['interest'] ?? 'HE IS FOCUSED IN HIS STUDIES';
    $teacher_remark = $fields['teacher_remark'] ?? 'GOOD PERFORMANCE. KEEP IT UP!';
    $headteacher_remark = $fields['headteacher_remark'] ?? '';
    $school_stamp = $fields['school_stamp'] ?? '';
    
    // Parse dates
    $closing_date = null;
    if (isset($fields['closing_date']) && !empty($fields['closing_date'])) {
        // Try to parse various date formats
        $closing_date = date('Y-m-d', strtotime($fields['closing_date']));
    } else {
        $closing_date = date('Y-m-d');
    }
    
    $reopening_date = null;
    if (isset($fields['reopening_date']) && !empty($fields['reopening_date'])) {
        $reopening_date = date('Y-m-d', strtotime($fields['reopening_date']));
    } else {
        $reopening_date = date('Y-m-d', strtotime('+30 days'));
    }

    if ($exists) {
        // Update existing
        $stmt = $conn->prepare("
            UPDATE report_details SET
                attendance_out_of = ?,
                attendance_total_days = ?,
                promoted_to = ?,
                conduct = ?,
                interest = ?,
                teacher_remark = ?,
                headteacher_remark = ?,
                closing_date = ?,
                reopening_date = ?,
                school_stamp = ?,
                director_signature = ?,
                headteacher_signature = ?,
                class_teacher_signature = ?
            WHERE student_id = ? AND term = ? AND academic_year = ?
        ");

        // 16 bind variables: ii + 11×s + i + ss
        $stmt->bind_param(
            "iisssssssssssiss",
            $attendance_out_of,
            $attendance_total_days,
            $promoted_to,
            $conduct,
            $interest,
            $teacher_remark,
            $headteacher_remark,
            $closing_date,
            $reopening_date,
            $school_stamp,
            $director_signature,
            $headteacher_signature,
            $classteacher_signature,
            $student_id,
            $term,
            $academic_year
        );
    } else {
        // Insert new
        $stmt = $conn->prepare("
            INSERT INTO report_details (
                student_id, term, academic_year,
                attendance_out_of, attendance_total_days, promoted_to, conduct, interest,
                teacher_remark, headteacher_remark, closing_date, reopening_date, school_stamp,
                director_signature, headteacher_signature, class_teacher_signature
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ");

        // 16 bind variables: iss + ii + 11×s
        $stmt->bind_param(
            "issiisssssssssss",
            $student_id,
            $term,
            $academic_year,
            $attendance_out_of,
            $attendance_total_days,
            $promoted_to,
            $conduct,
            $interest,
            $teacher_remark,
            $headteacher_remark,
            $closing_date,
            $reopening_date,
            $school_stamp,
            $director_signature,
            $headteacher_signature,
            $classteacher_signature
        );
    }

    if (!$stmt->execute()) {
        throw new Exception('Failed to save report details: ' . $stmt->error);
    }
    $stmt->close();

    // Update scores
    if (!empty($scores)) {
        foreach ($scores as $scoreData) {
            $subject_id = intval($scoreData['subject_id'] ?? 0);
            $field = $scoreData['field'] ?? '';
            $value = floatval($scoreData['value'] ?? 0);
            
            if (!$subject_id || !$field) continue;
            
            // Check if score exists
            $check_score = $conn->prepare("SELECT id FROM scores WHERE student_id = ? AND subject_id = ? AND term = ? AND academic_year = ?");
            $check_score->bind_param("iiss", $student_id, $subject_id, $term, $academic_year);
            $check_score->execute();
            $score_exists = $check_score->get_result()->num_rows > 0;
            $check_score->close();
            
            if ($score_exists) {
                if ($field === 'class_score') {
                    $update = $conn->prepare("UPDATE scores SET raw_class_score = ? WHERE student_id = ? AND subject_id = ? AND term = ? AND academic_year = ?");
                    $update->bind_param("diiss", $value, $student_id, $subject_id, $term, $academic_year);
                } else {
                    $update = $conn->prepare("UPDATE scores SET raw_exam_score = ? WHERE student_id = ? AND subject_id = ? AND term = ? AND academic_year = ?");
                    $update->bind_param("diiss", $value, $student_id, $subject_id, $term, $academic_year);
                }
            } else {
                // Insert new score record. class_name is stamped here as well as
                // in recalculateScores() below, because that helper returns early
                // when the class-subject has no configuration row — without this
                // the class snapshot would be lost for exactly those subjects.
                $score_class_name = academicStudentClass($conn, $student_id);
                if ($field === 'class_score') {
                    $update = $conn->prepare("
                        INSERT INTO scores (student_id, subject_id, class_name, raw_class_score, raw_exam_score, term, academic_year)
                        VALUES (?, ?, ?, ?, 0, ?, ?)
                    ");
                    $update->bind_param("iisdss", $student_id, $subject_id, $score_class_name, $value, $term, $academic_year);
                } else {
                    $update = $conn->prepare("
                        INSERT INTO scores (student_id, subject_id, class_name, raw_class_score, raw_exam_score, term, academic_year)
                        VALUES (?, ?, ?, 0, ?, ?, ?)
                    ");
                    $update->bind_param("iisdss", $student_id, $subject_id, $score_class_name, $value, $term, $academic_year);
                }
            }
            
            if (!$update->execute()) {
                throw new Exception('Failed to save score: ' . $update->error);
            }
            $update->close();
            
            // Recalculate weighted scores and grade
            recalculateScores($conn, $student_id, $subject_id, $term, $academic_year);
        }
    }

    $conn->commit();
    $response['success'] = true;
    $response['message'] = 'Report details saved successfully';

} catch (Exception $e) {
    $conn->rollback();
    $response['message'] = 'Database error: ' . $e->getMessage();
    error_log('Save report details error: ' . $e->getMessage());
}

$conn->close();
echo json_encode($response);
exit;

// Helper function to save signature image
function saveSignatureImage($signatureData, $type, $student_id, $term) {
    if (empty($signatureData) || strpos($signatureData, 'data:image/png;base64,') === false) {
        return '';
    }
    
    try {
        // Use __DIR__ so the path resolves correctly regardless of PHP's CWD
        $uploadDir = __DIR__ . '/../../../uploads/signatures/';
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }

        // Generate filename
        $cleanTerm = preg_replace('/[^a-zA-Z0-9]/', '_', $term);
        $filename  = 'sig_' . $type . '_' . $student_id . '_' . $cleanTerm . '_' . time() . '.png';
        $filepath  = $uploadDir . $filename;

        // Remove data URL prefix and decode
        $raw = preg_replace('/^data:image\/[a-z]+;base64,/', '', $signatureData);
        $raw = str_replace(' ', '+', $raw);
        $data = base64_decode($raw);

        if ($data === false) {
            return '';
        }

        // Save file
        if (file_put_contents($filepath, $data) !== false) {
            return 'uploads/signatures/' . $filename;
        }
    } catch (Exception $e) {
        error_log('Signature save error: ' . $e->getMessage());
    }
    
    return '';
}

// Helper function to recalculate scores - FIXED VERSION
function recalculateScores($conn, $student_id, $subject_id, $term, $academic_year) {
    try {
        // Get student's class
        $stmt = $conn->prepare("SELECT class FROM students WHERE id = ?");
        $stmt->bind_param("i", $student_id);
        $stmt->execute();
        $result = $stmt->get_result();
        $student = $result->fetch_assoc();
        
        if (!$student) return;
        
        $class_name = $student['class'];
        $stmt->close();
        
        // Get subject configuration
        $stmt = $conn->prepare("
            SELECT * FROM class_subjects 
            WHERE class_name = ? AND subject_id = ?
        ");
        $stmt->bind_param("si", $class_name, $subject_id);
        $stmt->execute();
        $result = $stmt->get_result();
        $config = $result->fetch_assoc();
        $stmt->close();
        
        if (!$config) return;
        
        // Get current raw scores
        $stmt = $conn->prepare("
            SELECT raw_class_score, raw_exam_score 
            FROM scores 
            WHERE student_id = ? AND subject_id = ? AND term = ? AND academic_year = ?
        ");
        $stmt->bind_param("iiss", $student_id, $subject_id, $term, $academic_year);
        $stmt->execute();
        $result = $stmt->get_result();
        $score = $result->fetch_assoc();
        $stmt->close();
        
        if ($score) {
            $raw_class = floatval($score['raw_class_score'] ?? 0);
            $raw_exam = floatval($score['raw_exam_score'] ?? 0);
            
            // Calculate weighted scores
            $max_class = floatval($config['max_class_score'] ?? 50);
            $max_exam = floatval($config['max_exam_score'] ?? 50);
            $class_percent = intval($config['class_score_percent'] ?? 50);
            $exam_percent = intval($config['exam_score_percent'] ?? 50);
            
            $weighted_class = $max_class > 0 ? ($raw_class / $max_class) * $class_percent : 0;
            $weighted_exam = $max_exam > 0 ? ($raw_exam / $max_exam) * $exam_percent : 0;
            $total = $weighted_class + $weighted_exam;
            
            // Determine grade
            $grade = 'W';
            $remark = 'Weak';
            
            $grade_stmt = $conn->prepare("
                SELECT * FROM grade_boundaries 
                WHERE class_name IN (?, 'ALL')
                ORDER BY min_score DESC
            ");
            $grade_stmt->bind_param("s", $class_name);
            $grade_stmt->execute();
            $grade_result = $grade_stmt->get_result();
            
            while ($row = $grade_result->fetch_assoc()) {
                if ($total >= floatval($row['min_score']) && $total <= floatval($row['max_score'])) {
                    $grade = $row['grade'];
                    $remark = $row['remark'];
                    break;
                }
            }
            $grade_stmt->close();
            
            // Update scores. This runs after every insert/update in this file, so
            // stamping class_name here covers both of the INSERT branches above
            // without threading the column through each of them.
            $update = $conn->prepare("
                UPDATE scores SET
                    weighted_class_score = ?,
                    weighted_exam_score = ?,
                    total_score = ?,
                    grade = ?,
                    remark = ?,
                    class_name = ?
                WHERE student_id = ? AND subject_id = ? AND term = ? AND academic_year = ?
            ");

            // 6 values for SET + 4 for WHERE = 10 parameters
            // Type string: dddsss for the 6 SET values, then iiss for the 4 WHERE conditions
            $update->bind_param(
                "dddsssiiss",  // 10 characters: d,d,d,s,s,s,i,i,s,s
                $weighted_class,
                $weighted_exam,
                $total,
                $grade,
                $remark,
                $class_name,
                $student_id,
                $subject_id,
                $term,
                $academic_year
            );
            
            if (!$update->execute()) {
                error_log('Error updating scores: ' . $update->error);
            }
            $update->close();
        }
    } catch (Exception $e) {
        error_log('Recalculate scores error: ' . $e->getMessage());
    }
}