<?php
// Filename: scan.php
require 'config.php';
header('Content-Type: application/json');

// --- HELPER: GPS DISTANCE ---
function getDistance($lat1, $lon1, $lat2, $lon2) {
    $R = 6371000; // Earth radius in meters
    $dLat = deg2rad($lat2 - $lat1); 
    $dLon = deg2rad($lon2 - $lon1);
    $a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLon / 2) * sin($dLon / 2);
    return $R * (2 * atan2(sqrt($a), sqrt(1-$a))); 
}

// --- HELPER: CHECK AUTHORIZATION ---
function isAuthorized($pdo, $tid, $uid, $date) {
    // 1. Original Teacher
    $stmt = $pdo->prepare("SELECT teacher_id FROM timetable WHERE id=?"); 
    $stmt->execute([$tid]); 
    $slot = $stmt->fetch();
    if($slot && $slot['teacher_id'] == $uid) return true;

    // 2. Relief Teacher
    $stmt = $pdo->prepare("SELECT reliever_id FROM relief_assignments WHERE timetable_id=? AND assignment_date=?"); 
    $stmt->execute([$tid, $date]); 
    $rel = $stmt->fetch();
    if($rel && $rel['reliever_id'] == $uid) return true;

    // 3. Admin Override (For Timetable Access, NOT GPS)
    $settings = $pdo->query("SELECT role FROM users WHERE id=$uid")->fetch();
    if($settings) {
        $roles = explode(',', $settings['role']);
        if(array_intersect(array_map('trim', $roles), ['admin', 'principal', 'assistant', 'timetable_coord'])) return true;
    }
    return false;
}

// --- MAIN LOGIC ---
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { 
    echo json_encode(['success'=>false,'message'=>'Invalid Request']); 
    exit; 
}

$input = json_decode(file_get_contents('php://input'), true);
$qr = $input['qr_token'] ?? ''; 
$lat = $input['lat'] ?? null; 
$lon = $input['lon'] ?? null;
$accuracy = $input['accuracy'] ?? null; // NEW: GPS accuracy in meters
$uid = $_SESSION['user_id'] ?? 0; 
$today = date('Y-m-d');

// 1. SETTINGS & GEO CHECK
$settings_rows = $pdo->query("SELECT * FROM system_settings")->fetchAll(PDO::FETCH_KEY_PAIR);
$geo_enabled = $settings_rows['geolocation_enabled'] ?? '1'; 
$accuracy_threshold = (int)($settings_rows['gps_accuracy_threshold'] ?? 100); // NEW: Max acceptable accuracy

if ($geo_enabled === '1') {
    $s_lat = $settings_rows['school_lat'] ?? ''; 
    $s_lon = $settings_rows['school_lon'] ?? ''; 
    $rad = $settings_rows['school_radius'] ?? 200;
    
    // Only perform check if School Coordinates are set in Admin Panel
    if ($s_lat && $s_lon) {
        // ERROR 1: Phone did not send GPS data
        if (empty($lat) || empty($lon)) {
            echo json_encode([
                'success'=>false, 
                'message'=>"GPS Location missing. Please allow location access on your phone."
            ]); 
            exit;
        }

        // NEW: Check GPS accuracy (optional - can be disabled)
        if ($accuracy !== null && $accuracy > $accuracy_threshold) {
            error_log("Low GPS accuracy warning: {$accuracy}m for user_id {$uid}");
            // Optional: You can reject if accuracy is too poor
            // echo json_encode([
            //     'success'=>false, 
            //     'message'=>"GPS accuracy too low (" . round($accuracy) . "m). Please wait for better signal."
            // ]); 
            // exit;
        }

        $dist = getDistance($s_lat, $s_lon, $lat, $lon);
        
        // ERROR 2: User is too far
        if ($dist > $rad) { 
            // Log suspicious attempts with location data
            try {
                $log_stmt = $pdo->prepare("
                    INSERT INTO security_logs (event_type, username, ip_address, details, created_at) 
                    VALUES ('geofence_violation', ?, ?, ?, NOW())
                ");
                $user_info = $pdo->prepare("SELECT username FROM users WHERE id=?")->execute([$uid]);
                $username = $pdo->fetch()['username'] ?? 'unknown';
                $details = json_encode([
                    'distance' => round($dist, 2),
                    'limit' => $rad,
                    'user_lat' => $lat,
                    'user_lon' => $lon,
                    'accuracy' => $accuracy
                ]);
                $log_stmt->execute([$username, $_SERVER['REMOTE_ADDR'], $details]);
            } catch (Exception $e) {
                error_log("Failed to log geofence violation: " . $e->getMessage());
            }

            echo json_encode([
                'success'=>false, 
                'message'=>"Too far from school! Detected: " . round($dist) . "m (Limit: {$rad}m)"
            ]); 
            exit; 
        }
    }
}

// 2. VALIDATE QR CODE
$stmt = $pdo->prepare("SELECT id, class_name FROM classes WHERE qr_token=?"); 
$stmt->execute([$qr]); 
$class = $stmt->fetch();

if(!$class) { 
    echo json_encode(['success'=>false, 'message'=>'Invalid Class QR Code']); 
    exit; 
}

// 3. FIND CURRENT TIMETABLE SLOT
$now = date('H:i:s'); 
$day = date('N'); 

// A. Active slot
$stmt = $pdo->prepare("
    SELECT id, subject, start_time, end_time 
    FROM timetable 
    WHERE class_id=? AND day_of_week=? AND ? BETWEEN start_time AND end_time
");
$stmt->execute([$class['id'], $day, $now]); 
$curr_slot = $stmt->fetch();
$status = 'present';

// B. Recent past slot
if(!$curr_slot) { 
    $stmt = $pdo->prepare("
        SELECT t.id, t.subject, t.start_time, t.end_time 
        FROM timetable t
        LEFT JOIN attendance_logs al ON t.id = al.timetable_id AND DATE(al.scan_time) = ?
        WHERE t.class_id=? AND t.day_of_week=? AND t.end_time < ? 
        AND al.id IS NULL 
        ORDER BY t.end_time DESC LIMIT 1
    ");
    $stmt->execute([$today, $class['id'], $day, $now]);
    $curr_slot = $stmt->fetch();
    if ($curr_slot) $status = 'late'; 
}

if(!$curr_slot) { 
    echo json_encode([
        'success'=>false, 
        'message'=>"No active class found for {$class['class_name']}."
    ]); 
    exit; 
}

// 4. CHECK AUTHORIZATION
if(!isAuthorized($pdo, $curr_slot['id'], $uid, $today)) { 
    echo json_encode(['success'=>false, 'message'=>'Not authorized for this class.']); 
    exit; 
}

// 5. DETECT CONSECUTIVE PERIODS
$slots_to_mark = [$curr_slot['id']];
$current_subject = trim($curr_slot['subject']);

// 5A. Backward Check
$check_start_time = $curr_slot['start_time'];
while(true) {
    $prev_stmt = $pdo->prepare("
        SELECT id, subject, start_time, end_time 
        FROM timetable 
        WHERE class_id=? AND day_of_week=? AND end_time = ?
    ");
    $prev_stmt->execute([$class['id'], $day, $check_start_time]);
    $prev_slot = $prev_stmt->fetch();

    if ($prev_slot && trim($prev_slot['subject']) == $current_subject && isAuthorized($pdo, $prev_slot['id'], $uid, $today)) {
        $chk_log = $pdo->prepare("SELECT id FROM attendance_logs WHERE timetable_id=? AND DATE(scan_time)=?");
        $chk_log->execute([$prev_slot['id'], $today]);
        if (!$chk_log->fetch()) {
            array_unshift($slots_to_mark, $prev_slot['id']); 
            $check_start_time = $prev_slot['start_time']; 
            continue; 
        }
    }
    break; 
}

// 5B. Forward Check
$last_end_time = $curr_slot['end_time'];
$future_stmt = $pdo->prepare("
    SELECT id, subject, start_time, end_time 
    FROM timetable 
    WHERE class_id=? AND day_of_week=? AND start_time >= ? 
    ORDER BY start_time ASC
");
$future_stmt->execute([$class['id'], $day, $last_end_time]);
$future_slots = $future_stmt->fetchAll();

foreach ($future_slots as $next_slot) {
    if ($next_slot['start_time'] == $last_end_time && trim($next_slot['subject']) == $current_subject) {
        if (isAuthorized($pdo, $next_slot['id'], $uid, $today)) {
            $slots_to_mark[] = $next_slot['id'];
            $last_end_time = $next_slot['end_time']; 
        } else { break; }
    } else { break; }
}

// 6. EXECUTE LOGGING (ENHANCED with GPS data)
$marked_count = 0;

// UPDATED: Include latitude, longitude, and accuracy in attendance_logs
$log_stmt = $pdo->prepare("
    INSERT INTO attendance_logs 
    (timetable_id, user_id, class_id, status, scan_time, latitude, longitude, gps_accuracy) 
    VALUES (?, ?, ?, ?, NOW(), ?, ?, ?)
");

$check_stmt = $pdo->prepare("
    SELECT id FROM attendance_logs 
    WHERE timetable_id=? AND DATE(scan_time)=?
");

foreach ($slots_to_mark as $tid) {
    $check_stmt->execute([$tid, $today]);
    if (!$check_stmt->fetch()) {
        try {
            if ($log_stmt->execute([
                $tid, 
                $uid, 
                $class['id'], 
                $status,
                $lat,      // Store latitude
                $lon,      // Store longitude
                $accuracy  // Store GPS accuracy
            ])) {
                $marked_count++;
            }
        } catch (PDOException $e) {
            // Fallback if columns don't exist yet
            error_log("GPS columns may not exist in attendance_logs: " . $e->getMessage());
            
            // Try without GPS data
            $fallback_stmt = $pdo->prepare("
                INSERT INTO attendance_logs 
                (timetable_id, user_id, class_id, status, scan_time) 
                VALUES (?, ?, ?, ?, NOW())
            ");
            if ($fallback_stmt->execute([$tid, $uid, $class['id'], $status])) {
                $marked_count++;
            }
        }
    }
}

// 7. RETURN RESPONSE
if ($marked_count > 0) {
    $msg = ($marked_count > 1) 
        ? "Marked $marked_count continuous periods." 
        : "Attendance marked.";
    
    // Add accuracy info to success message if available
    if ($accuracy !== null && $accuracy <= 20) {
        $msg .= " (GPS: Excellent)";
    } elseif ($accuracy !== null && $accuracy <= 50) {
        $msg .= " (GPS: Good)";
    } elseif ($accuracy !== null) {
        $msg .= " (GPS: " . round($accuracy) . "m)";
    }
    
    echo json_encode([
        'success' => true, 
        'message' => $msg, 
        'redirectUrl' => "class_session.php?timetable_id=" . $curr_slot['id']
    ]);
} else {
    echo json_encode([
        'success' => true, 
        'message' => "Attendance already marked.", 
        'redirectUrl' => "class_session.php?timetable_id=" . $curr_slot['id']
    ]);
}
?>