<?php
require_once 'config/database.php';
require_once 'utils/helpers.php';

date_default_timezone_set('UTC');

try {

    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        Helpers::sendResponse(false, 'Method not allowed', null, 405);
    }

    // Get and verify token
    $token = Helpers::getBearerToken();
    $userData = Helpers::verifyJWT($token);

    if (!$userData) {
        Helpers::sendResponse(false, 'Unauthorized', null, 401);
    }

    $data = json_decode(file_get_contents("php://input"));

    if (empty($data->service_occurrence_id) || !isset($data->latitude) || !isset($data->longitude)) {
        Helpers::sendResponse(false, 'Service occurrence ID and location are required', null, 400);
    }

    $database = new Database();
    $db = $database->getConnection();

    // Verify user has permission to clock in
    $query = "SELECT ur.`can_clock_in` 
          FROM `users` u 
          JOIN `user_roles` ur ON u.`role_id` = ur.id 
          WHERE u.`id` = :user_id AND u.`is_active` = TRUE";

    $stmt = $db->prepare($query);
    $stmt->bindParam(':user_id', $userData['user_id']);
    $stmt->execute();

    if ($stmt->rowCount() === 0) {
        Helpers::sendResponse(false, 'User not found or inactive', null, 404);
    }

    $userRole = $stmt->fetch();
    if (!$userRole['can_clock_in']) {
        Helpers::sendResponse(false, 'You do not have permission to clock in', null, 403);
    }

    $query = "SELECT so.`id`, so.`service_template_id`, so.`start_time`, so.`end_time`, 
                 so.`is_active`, so.`was_cancelled`,
                 st.`name`, st.`location`, st.`latitude`, st.`longitude`, 
                 st.`geofence_radius`, stype.`allows_delegates`
          FROM `service_occurrences` so
          JOIN `service_templates` st ON so.`service_template_id` = st.`id`
          LEFT JOIN `service_types` stype ON st.`service_type_id` = stype.id
          WHERE so.`id` = :service_occurrence_id 
          AND so.`is_active` = TRUE 
          AND so.`was_cancelled` = FALSE";

    $stmt = $db->prepare($query);
    $stmt->bindParam(':service_occurrence_id', $data->service_occurrence_id);
    $stmt->execute();

    if ($stmt->rowCount() === 0) {
        Helpers::sendResponse(false, 'Service occurrence not found, inactive, or cancelled', null, 404);
    }

    $serviceOccurrence = $stmt->fetch();

    // Check if service is currently active (allow clock in 1 hour before start)
    $now = time();
    $startTime = strtotime($serviceOccurrence['start_time']);
    $endTime = strtotime($serviceOccurrence['end_time']);
    $oneHourBeforeStart = $startTime - 3600;
    $oneHourAfterEnd = $endTime + 3600;

    if ($now < $oneHourBeforeStart) {
        $minutesUntil = ceil(($oneHourBeforeStart - $now) / 60);
        Helpers::sendResponse(false, "Service clock-in opens in {$minutesUntil} minutes", null, 400);
    }

    if ($now > $oneHourAfterEnd) {
        Helpers::sendResponse(false, 'Service has ended. Clock-in period closed.', null, 400);
    }

    $query = "SELECT a.`id`, a.`clock_out_time` 
              FROM `attendance` a 
              WHERE a.`user_id` = :user_id 
              AND a.`service_occurrence_id` = :service_occurrence_id";

    $stmt = $db->prepare($query);
    $stmt->bindParam(':user_id', $userData['user_id']);
    $stmt->bindParam(':service_occurrence_id', $data->service_occurrence_id);
    $stmt->execute();

    if ($stmt->rowCount() > 0) {
        $existingAttendance = $stmt->fetch();
        if (empty($existingAttendance['clock_out_time'])) {
            Helpers::sendResponse(false, 'You are already clocked in for this service. Please clock out first.', null, 400);
        } else {
            Helpers::sendResponse(false, 'You have already completed attendance for this service occurrence', null, 400);
        }
    }

    // Verify user is within geofence
    if (!empty($serviceOccurrence['latitude']) && !empty($serviceOccurrence['longitude'])) {
        $distance = Helpers::calculateDistance(
            $data->latitude,
            $data->longitude,
            $serviceOccurrence['latitude'],
            $serviceOccurrence['longitude']
        );

        if ($distance > $serviceOccurrence['geofence_radius']) {
            Helpers::sendResponse(false, 'You are not within the service location. Please move closer to the venue.', [
                'distance' => round($distance, 2),
                'required' => $serviceOccurrence['geofence_radius']
            ], 400);
        }
    }

    $query = "INSERT INTO `attendance` 
          (`user_id`, `service_occurrence_id`, `clock_in_time`, `clock_in_latitude`, `clock_in_longitude`, `is_valid`) 
          VALUES (:user_id, :service_occurrence_id, NOW(), :latitude, :longitude, TRUE)";

    $stmt = $db->prepare($query);
    $stmt->bindParam(':user_id', $userData['user_id']);
    $stmt->bindParam(':service_occurrence_id', $data->service_occurrence_id);
    $stmt->bindParam(':latitude', $data->latitude);
    $stmt->bindParam(':longitude', $data->longitude);

    if ($stmt->execute()) {
        $attendanceId = $db->lastInsertId();

        Helpers::sendResponse(true, 'Clocked in successfully', [
            'attendance_id' => $attendanceId,
            'service_name' => $serviceOccurrence['name'],
            'clock_in_time' => date('Y-m-d H:i:s')
        ], 201);
    } else {
        Helpers::sendResponse(false, 'Clock in failed', null, 500);
    }
} catch (PDOException $e) {
    ErrorLogger::logDatabaseError($e, $userData['user_id'] ?? 'unknown', [
        'endpoint' => 'attendance/clock-in',
        'user_id' => $userData['user_id'] ?? 'unknown'
    ]);
    Helpers::sendResponse(false, 'Database error: ' . $e->getMessage(), null, 500);
} catch (Exception $e) {
    ErrorLogger::logError($e, [
        'endpoint' => 'attendance/clock-in',
        'user_id' => $userData['user_id'] ?? 'unknown'
    ]);
    Helpers::sendResponse(false, 'Error: ' . $e->getMessage(), null, 500);
}
