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

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"));

    // Validate required fields
    if (empty($data->attendance_id) || !isset($data->latitude) || !isset($data->longitude)) {
        Helpers::sendResponse(false, 'Attendance ID and location are required', null, 400);
    }

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

    $query = "SELECT a.id, a.user_id, a.service_occurrence_id, a.clock_in_time, a.clock_out_time,
                     st.latitude, st.longitude, st.geofence_radius, st.name as service_name
              FROM `attendance` a
              JOIN `service_occurrences` so ON a.`service_occurrence_id` = so.`id`
              JOIN `service_templates` st ON so.`service_template_id` = st.`id`
              WHERE a.`id` = :attendance_id AND a.`user_id` = :user_id";

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

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

    $attendance = $stmt->fetch();

    // Check if already clocked out
    if ($attendance['clock_out_time']) {
        Helpers::sendResponse(false, 'You have already clocked out', null, 400);
    }

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

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

    // Calculate time spent
    $clockInTime = new DateTime($attendance['clock_in_time']);
    $clockOutTime = new DateTime();
    $interval = $clockInTime->diff($clockOutTime);
    $timeSpent = ($interval->h * 60) + $interval->i;

    $isValid = $timeSpent >= 30;

    // Update attendance record
    $query = "UPDATE `attendance` 
              SET `clock_out_time` = NOW(),
                  `clock_out_latitude` = :latitude,
                  `clock_out_longitude` = :longitude,
                  `time_spent` = :time_spent,
                  `is_valid` = :is_valid
              WHERE `id` = :attendance_id";

    $stmt = $db->prepare($query);
    $stmt->bindParam(':latitude', $data->latitude);
    $stmt->bindParam(':longitude', $data->longitude);
    $stmt->bindParam(':time_spent', $timeSpent);
    $stmt->bindParam(':is_valid', $isValid, PDO::PARAM_BOOL);
    $stmt->bindParam(':attendance_id', $data->attendance_id);

    if ($stmt->execute()) {
        $query = "SELECT sr.id, sr.reward_id, sr.attendance_required, r.name as reward_name
                  FROM `service_rewards` sr
                  JOIN `service_occurrences` so ON sr.`service_template_id` = so.`service_template_id`
                  JOIN `rewards` r ON sr.`reward_id` = r.`id`
                  WHERE so.`id` = :service_occurrence_id 
                  AND sr.`is_active` = TRUE
                  AND sr.`start_date` <= NOW()
                  AND (sr.`end_date` IS NULL OR sr.`end_date` >= NOW())";

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

        $rewardInfo = null;
        if ($stmt->rowCount() > 0 && $isValid) {
            $serviceReward = $stmt->fetch();

            // Check or create user reward progress
            $query = "SELECT id, attendance_count, rewards_earned 
                      FROM `users_service_rewards` 
                      WHERE `user_id` = :user_id AND `service_reward_id` = :service_reward_id";

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

            if ($stmt->rowCount() > 0) {
                // Update existing progress
                $progress = $stmt->fetch();
                $newCount = $progress['attendance_count'] + 1;
                $newRewards = $progress['rewards_earned'];

                // Check if user earned a new reward
                if ($newCount >= $serviceReward['attendance_required'] && $newCount % $serviceReward['attendance_required'] === 0) {
                    $newRewards++;
                    $rewardInfo = [
                        'earned' => true,
                        'reward_name' => $serviceReward['reward_name'],
                        'attendance_count' => $newCount
                    ];
                }

                $query = "UPDATE `users_service_rewards` 
                          SET `attendance_count` = :attendance_count,
                              `rewards_earned` = :rewards_earned,
                              `last_attendance_date` = NOW()
                          WHERE `id` = :id";

                $stmt = $db->prepare($query);
                $stmt->bindParam(':attendance_count', $newCount);
                $stmt->bindParam(':rewards_earned', $newRewards);
                $stmt->bindParam(':id', $progress['id']);
                $stmt->execute();
            } else {
                // Create new progress record
                $query = "INSERT INTO `users_service_rewards` 
                          (`user_id`, `service_reward_id`, `attendance_count`, `last_attendance_date`) 
                          VALUES (:user_id, :service_reward_id, 1, NOW())";

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

        $response = [
            'clock_out_time' => date('Y-m-d H:i:s'),
            'time_spent' => $timeSpent,
            'is_valid' => $isValid
        ];

        if ($rewardInfo) {
            $response['reward'] = $rewardInfo;
        }

        if (!$isValid) {
            $response['warning'] = 'Attendance marked as invalid (less than 30 minutes). This will not count toward rewards.';
        }

        Helpers::sendResponse(true, 'Clocked out successfully', $response);
    } else {
        Helpers::sendResponse(false, 'Clock out failed', null, 500);
    }
} catch (PDOException $e) {
    ErrorLogger::logDatabaseError($e, $userData['user_id'] ?? 'unknown', [
        'endpoint' => 'attendance/clock-out',
        'user_id' => $userData['user_id'] ?? 'unknown'
    ]);
    Helpers::sendResponse(false, 'Database error: ' . $e->getMessage(), null, 500);
} catch (Exception $e) {
    ErrorLogger::logError($e, [
        'endpoint' => 'attendance/clock-out',
        'user_id' => $userData['user_id'] ?? 'unknown'
    ]);
    Helpers::sendResponse(false, 'Error: ' . $e->getMessage(), null, 500);
}
