<?php

/**
 * Admin Attendance Management API
 * Handles CRUD operations for attendance records
 */
require_once 'config/database.php';
require_once 'utils/helpers.php';

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

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

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

    // Verify admin/HOD access
    $query = "SELECT ur.role_level, ur.can_view_department_attendance 
              FROM users u 
              JOIN user_roles ur ON u.role_id = ur.id 
              WHERE u.id = :user_id";
    $stmt = $db->prepare($query);
    $stmt->bindParam(':user_id', $userData['user_id']);
    $stmt->execute();
    $userRole = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$userRole || $userRole['role_level'] < 3) {
        Helpers::sendResponse(false, 'Unauthorized. Attendance management access required.', null, 403);
    }

    $method = $_SERVER['REQUEST_METHOD'];

    // GET: Retrieve attendance records
    if ($method === 'GET') {
        $serviceId = isset($_GET['service_id']) ? intval($_GET['service_id']) : 0;
        $userId = isset($_GET['user_id']) ? intval($_GET['user_id']) : 0;
        $departmentId = isset($_GET['department_id']) ? intval($_GET['department_id']) : 0;
        $startDate = isset($_GET['start_date']) ? $_GET['start_date'] : date('Y-m-d', strtotime('-30 days'));
        $endDate = isset($_GET['end_date']) ? $_GET['end_date'] : date('Y-m-d');
        $validOnly = isset($_GET['valid_only']) ? filter_var($_GET['valid_only'], FILTER_VALIDATE_BOOLEAN) : true;
        $limit = isset($_GET['limit']) ? intval($_GET['limit']) : 100;
        $offset = isset($_GET['offset']) ? intval($_GET['offset']) : 0;

        $whereConditions = [];
        $params = [];

        // Date range filter
        $whereConditions[] = "DATE(a.clock_in_time) BETWEEN :start_date AND :end_date";
        $params[':start_date'] = $startDate;
        $params[':end_date'] = $endDate;

        // Service filter
        if ($serviceId > 0) {
            $whereConditions[] = "a.service_id = :service_id";
            $params[':service_id'] = $serviceId;
        }

        // User filter
        if ($userId > 0) {
            $whereConditions[] = "a.user_id = :user_id";
            $params[':user_id'] = $userId;
        }

        // Department filter
        if ($departmentId > 0) {
            $whereConditions[] = "u.department_id = :department_id";
            $params[':department_id'] = $departmentId;
        }

        // Valid attendance only
        if ($validOnly) {
            $whereConditions[] = "a.is_valid = TRUE";
        }

        $whereClause = 'WHERE ' . implode(' AND ', $whereConditions);

        // Get total count for pagination
        $countQuery = "SELECT COUNT(*) as total 
                       FROM attendance a
                       JOIN users u ON a.user_id = u.id
                       JOIN services s ON a.service_id = s.id
                       $whereClause";

        $stmt = $db->prepare($countQuery);
        foreach ($params as $key => $value) {
            $stmt->bindValue($key, $value);
        }
        $stmt->execute();
        $totalCount = $stmt->fetch(PDO::FETCH_ASSOC)['total'];

        // Get attendance records
        $query = "SELECT a.id, a.user_id, a.service_id,
                         a.clock_in_time, a.clock_out_time, a.time_spent,
                         a.clock_in_latitude, a.clock_in_longitude,
                         a.clock_out_latitude, a.clock_out_longitude,
                         a.is_valid, a.notes, a.created_at, a.updated_at,
                         CONCAT(u.first_name, ' ', u.last_name) as user_name,
                         u.email as user_email, u.avatar_url,
                         d.name as department_name,
                         ur.role_name,
                         s.name as service_name, s.location as service_location, s.start_time AS service_start_date, 
                         st.name as service_type
                  FROM attendance a
                  JOIN users u ON a.user_id = u.id
                  LEFT JOIN departments d ON u.department_id = d.id
                  JOIN user_roles ur ON u.role_id = ur.id
                  JOIN services s ON a.service_id = s.id
                  LEFT JOIN service_types st ON s.service_type_id = st.id
                  $whereClause
                  ORDER BY a.clock_in_time DESC
                  LIMIT :limit OFFSET :offset";

        $stmt = $db->prepare($query);
        foreach ($params as $key => $value) {
            $stmt->bindValue($key, $value);
        }
        $stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
        $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
        $stmt->execute();

        $attendanceRecords = $stmt->fetchAll(PDO::FETCH_ASSOC);

        // Get summary statistics
        $statsQuery = "SELECT 
                           COUNT(DISTINCT a.user_id) as unique_attendees,
                           COUNT(a.id) as total_records,
                           AVG(a.time_spent) as avg_time_spent,
                           SUM(a.time_spent) as total_time_spent
                       FROM attendance a
                       JOIN users u ON a.user_id = u.id
                       $whereClause";

        $stmt = $db->prepare($statsQuery);
        foreach ($params as $key => $value) {
            $stmt->bindValue($key, $value);
        }
        $stmt->execute();
        $stats = $stmt->fetch(PDO::FETCH_ASSOC);

        Helpers::sendResponse(true, 'Attendance records retrieved successfully', [
            'attendance' => $attendanceRecords,
            'count' => count($attendanceRecords),
            'total' => (int)$totalCount,
            'page' => floor($offset / $limit) + 1,
            'total_pages' => ceil($totalCount / $limit),
            'statistics' => $stats,
            'filters' => [
                'start_date' => $startDate,
                'end_date' => $endDate,
                'service_id' => $serviceId,
                'user_id' => $userId,
                'department_id' => $departmentId
            ]
        ]);
    }

    // POST: Create manual attendance record
    elseif ($method === 'POST') {
        $data = json_decode(file_get_contents("php://input"));

        // Validate required fields
        if (empty($data->user_id) || empty($data->service_id) || empty($data->clock_in_time)) {
            Helpers::sendResponse(false, 'User ID, service ID, and clock in time are required', null, 400);
        }

        // Verify user exists
        $query = "SELECT id, first_name, last_name FROM users WHERE id = :user_id AND is_active = TRUE";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':user_id', $data->user_id);
        $stmt->execute();
        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$user) {
            Helpers::sendResponse(false, 'User not found or inactive', null, 404);
        }

        // Verify service exists
        $query = "SELECT id, name FROM services WHERE id = :service_id";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':service_id', $data->service_id);
        $stmt->execute();
        $service = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$service) {
            Helpers::sendResponse(false, 'Service not found', null, 404);
        }

        // Check for duplicate attendance
        $query = "SELECT id FROM attendance 
                  WHERE user_id = :user_id 
                  AND service_id = :service_id 
                  AND DATE(clock_in_time) = DATE(:clock_in_time)";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':user_id', $data->user_id);
        $stmt->bindParam(':service_id', $data->service_id);
        $stmt->bindParam(':clock_in_time', $data->clock_in_time);
        $stmt->execute();

        if ($stmt->rowCount() > 0) {
            Helpers::sendResponse(false, 'Attendance record already exists for this user and service on this date', null, 409);
        }

        // Calculate time spent if clock_out_time is provided
        $timeSpent = null;
        if (!empty($data->clock_out_time)) {
            $clockIn = new DateTime($data->clock_in_time);
            $clockOut = new DateTime($data->clock_out_time);
            $interval = $clockIn->diff($clockOut);
            $timeSpent = ($interval->h * 60) + $interval->i; // Convert to minutes
        }

        // Insert attendance record
        $query = "INSERT INTO attendance 
                  (user_id, service_id, clock_in_time, clock_out_time, 
                   clock_in_latitude, clock_in_longitude, 
                   clock_out_latitude, clock_out_longitude,
                   time_spent, is_valid, notes, created_at) 
                  VALUES 
                  (:user_id, :service_id, :clock_in_time, :clock_out_time,
                   :clock_in_lat, :clock_in_lng,
                   :clock_out_lat, :clock_out_lng,
                   :time_spent, :is_valid, :notes, NOW())";

        $stmt = $db->prepare($query);
        $stmt->bindParam(':user_id', $data->user_id);
        $stmt->bindParam(':service_id', $data->service_id);
        $stmt->bindParam(':clock_in_time', $data->clock_in_time);
        $clockOutTime = $data->clock_out_time ?? null;
        $stmt->bindParam(':clock_out_time', $clockOutTime);
        $clockInLat = $data->clock_in_latitude ?? null;
        $stmt->bindParam(':clock_in_lat', $clockInLat);
        $clockInLng = $data->clock_in_longitude ?? null;
        $stmt->bindParam(':clock_in_lng', $clockInLng);
        $clockOutLat = $data->clock_out_latitude ?? null;
        $stmt->bindParam(':clock_out_lat', $clockOutLat);
        $clockOutLng = $data->clock_out_longitude ?? null;
        $stmt->bindParam(':clock_out_lng', $clockOutLng);
        $stmt->bindParam(':time_spent', $timeSpent);
        $isValid = isset($data->is_valid) ? (bool)$data->is_valid : true;
        $stmt->bindParam(':is_valid', $isValid, PDO::PARAM_BOOL);
        $notes = $data->notes ?? 'Manually added by admin';
        $stmt->bindParam(':notes', $notes);

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

            // Check if this attendance qualifies for any rewards
            $rewardQuery = "SELECT sr.id, sr.attendance_required, sr.reward_id
                           FROM service_rewards sr
                           WHERE sr.service_id = :service_id 
                           AND sr.is_active = TRUE
                           AND (sr.start_date IS NULL OR sr.start_date <= NOW())
                           AND (sr.end_date IS NULL OR sr.end_date >= NOW())";

            $stmt = $db->prepare($rewardQuery);
            $stmt->bindParam(':service_id', $data->service_id);
            $stmt->execute();
            $serviceRewards = $stmt->fetchAll(PDO::FETCH_ASSOC);

            foreach ($serviceRewards as $reward) {
                // Update or create user reward progress
                $checkQuery = "SELECT id, attendance_count FROM users_service_rewards 
                              WHERE user_id = :user_id AND service_reward_id = :service_reward_id";
                $checkStmt = $db->prepare($checkQuery);
                $checkStmt->bindParam(':user_id', $data->user_id);
                $checkStmt->bindParam(':service_reward_id', $reward['id']);
                $checkStmt->execute();
                $userReward = $checkStmt->fetch(PDO::FETCH_ASSOC);

                if ($userReward) {
                    // Update existing progress
                    $newCount = $userReward['attendance_count'] + 1;
                    $updateQuery = "UPDATE users_service_rewards 
                                   SET attendance_count = :count, 
                                       last_attendance_date = NOW(),
                                       updated_at = NOW()
                                   WHERE id = :id";
                    $updateStmt = $db->prepare($updateQuery);
                    $updateStmt->bindParam(':count', $newCount);
                    $updateStmt->bindParam(':id', $userReward['id']);
                    $updateStmt->execute();
                } else {
                    // Create new progress record
                    $insertQuery = "INSERT INTO users_service_rewards 
                                   (user_id, service_reward_id, attendance_count, last_attendance_date, created_at)
                                   VALUES (:user_id, :service_reward_id, 1, NOW(), NOW())";
                    $insertStmt = $db->prepare($insertQuery);
                    $insertStmt->bindParam(':user_id', $data->user_id);
                    $insertStmt->bindParam(':service_reward_id', $reward['id']);
                    $insertStmt->execute();
                }
            }

            // Log admin activity
            $logQuery = "INSERT INTO admin_logs 
                        (admin_id, action, action_type, target_type, target_id, details, ip_address, created_at) 
                        VALUES 
                        (:admin_id, 'create_attendance', 'create', 'attendance', :attendance_id, :details, :ip, NOW())";

            $details = json_encode([
                'user' => $user['first_name'] . ' ' . $user['last_name'],
                'service' => $service['name'],
                'clock_in' => $data->clock_in_time
            ]);
            $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';

            $stmt = $db->prepare($logQuery);
            $stmt->bindParam(':admin_id', $userData['user_id']);
            $stmt->bindParam(':attendance_id', $newAttendanceId);
            $stmt->bindParam(':details', $details);
            $stmt->bindParam(':ip', $ip);
            $stmt->execute();

            Helpers::sendResponse(true, 'Attendance record created successfully', [
                'attendance_id' => $newAttendanceId,
                'time_spent' => $timeSpent
            ], 201);
        } else {
            Helpers::sendResponse(false, 'Failed to create attendance record', null, 500);
        }
    }

    // PUT: Update attendance record
    elseif ($method === 'PUT') {
        $attendanceId = isset($_GET['id']) ? intval($_GET['id']) : null;

        if (!$attendanceId) {
            Helpers::sendResponse(false, 'Attendance ID is required', null, 400);
        }

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

        // Check if attendance record exists
        $query = "SELECT id, user_id, service_id, clock_in_time, clock_out_time 
                  FROM attendance WHERE id = :attendance_id";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':attendance_id', $attendanceId);
        $stmt->execute();
        $existingRecord = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$existingRecord) {
            Helpers::sendResponse(false, 'Attendance record not found', null, 404);
        }

        // Build dynamic update query
        $updateFields = [];
        $params = [':attendance_id' => $attendanceId];

        if (isset($data->clock_in_time)) {
            $updateFields[] = "clock_in_time = :clock_in_time";
            $params[':clock_in_time'] = $data->clock_in_time;
        }

        if (isset($data->clock_out_time)) {
            $updateFields[] = "clock_out_time = :clock_out_time";
            $params[':clock_out_time'] = $data->clock_out_time;

            // Recalculate time spent
            $clockIn = new DateTime($existingRecord['clock_in_time']);
            if (isset($data->clock_in_time)) {
                $clockIn = new DateTime($data->clock_in_time);
            }
            $clockOut = new DateTime($data->clock_out_time);
            $interval = $clockIn->diff($clockOut);
            $timeSpent = ($interval->h * 60) + $interval->i;

            $updateFields[] = "time_spent = :time_spent";
            $params[':time_spent'] = $timeSpent;
        }

        if (isset($data->clock_in_latitude)) {
            $updateFields[] = "clock_in_latitude = :clock_in_lat";
            $params[':clock_in_lat'] = $data->clock_in_latitude;
        }

        if (isset($data->clock_in_longitude)) {
            $updateFields[] = "clock_in_longitude = :clock_in_lng";
            $params[':clock_in_lng'] = $data->clock_in_longitude;
        }

        if (isset($data->clock_out_latitude)) {
            $updateFields[] = "clock_out_latitude = :clock_out_lat";
            $params[':clock_out_lat'] = $data->clock_out_latitude;
        }

        if (isset($data->clock_out_longitude)) {
            $updateFields[] = "clock_out_longitude = :clock_out_lng";
            $params[':clock_out_lng'] = $data->clock_out_longitude;
        }

        if (isset($data->is_valid)) {
            $updateFields[] = "is_valid = :is_valid";
            $params[':is_valid'] = (bool)$data->is_valid;
        }

        if (isset($data->notes)) {
            $updateFields[] = "notes = :notes";
            $params[':notes'] = $data->notes;
        }

        if (empty($updateFields)) {
            Helpers::sendResponse(false, 'No fields to update', null, 400);
        }

        $updateFields[] = "updated_at = NOW()";

        $query = "UPDATE attendance SET " . implode(', ', $updateFields) . " WHERE id = :attendance_id";
        $stmt = $db->prepare($query);

        foreach ($params as $key => $value) {
            $stmt->bindValue($key, $value);
        }

        if ($stmt->execute()) {
            // Log admin activity
            $logQuery = "INSERT INTO admin_logs 
                        (admin_id, action, action_type, target_type, target_id, details, ip_address, created_at) 
                        VALUES 
                        (:admin_id, 'update_attendance', 'update', 'attendance', :attendance_id, :details, :ip, NOW())";

            $details = json_encode($data);
            $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';

            $stmt = $db->prepare($logQuery);
            $stmt->bindParam(':admin_id', $userData['user_id']);
            $stmt->bindParam(':attendance_id', $attendanceId);
            $stmt->bindParam(':details', $details);
            $stmt->bindParam(':ip', $ip);
            $stmt->execute();

            Helpers::sendResponse(true, 'Attendance record updated successfully');
        } else {
            Helpers::sendResponse(false, 'Failed to update attendance record', null, 500);
        }
    }

    // DELETE: Delete attendance record
    elseif ($method === 'DELETE') {
        $attendanceId = isset($_GET['id']) ? intval($_GET['id']) : null;

        if (!$attendanceId) {
            Helpers::sendResponse(false, 'Attendance ID is required', null, 400);
        }

        // Get attendance info before deletion
        $query = "SELECT a.id, a.user_id, a.service_id,
                         CONCAT(u.first_name, ' ', u.last_name) as user_name,
                         s.name as service_name
                  FROM attendance a
                  JOIN users u ON a.user_id = u.id
                  JOIN services s ON a.service_id = s.id
                  WHERE a.id = :attendance_id";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':attendance_id', $attendanceId);
        $stmt->execute();
        $attendance = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$attendance) {
            Helpers::sendResponse(false, 'Attendance record not found', null, 404);
        }

        // Update reward progress (decrement count)
        $rewardQuery = "SELECT usr.id, usr.attendance_count, sr.id as service_reward_id
                       FROM users_service_rewards usr
                       JOIN service_rewards sr ON usr.service_reward_id = sr.id
                       WHERE usr.user_id = :user_id AND sr.service_id = :service_id";

        $stmt = $db->prepare($rewardQuery);
        $stmt->bindParam(':user_id', $attendance['user_id']);
        $stmt->bindParam(':service_id', $attendance['service_id']);
        $stmt->execute();
        $userRewards = $stmt->fetchAll(PDO::FETCH_ASSOC);

        foreach ($userRewards as $reward) {
            if ($reward['attendance_count'] > 0) {
                $newCount = $reward['attendance_count'] - 1;
                $updateQuery = "UPDATE users_service_rewards 
                               SET attendance_count = :count, updated_at = NOW()
                               WHERE id = :id";
                $updateStmt = $db->prepare($updateQuery);
                $updateStmt->bindParam(':count', $newCount);
                $updateStmt->bindParam(':id', $reward['id']);
                $updateStmt->execute();
            }
        }

        // Delete attendance record
        $query = "DELETE FROM attendance WHERE id = :attendance_id";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':attendance_id', $attendanceId);

        if ($stmt->execute()) {
            // Log admin activity
            $logQuery = "INSERT INTO admin_logs 
                        (admin_id, action, action_type, target_type, target_id, details, ip_address, created_at) 
                        VALUES 
                        (:admin_id, 'delete_attendance', 'delete', 'attendance', :attendance_id, :details, :ip, NOW())";

            $details = json_encode([
                'user' => $attendance['user_name'],
                'service' => $attendance['service_name']
            ]);
            $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';

            $stmt = $db->prepare($logQuery);
            $stmt->bindParam(':admin_id', $userData['user_id']);
            $stmt->bindParam(':attendance_id', $attendanceId);
            $stmt->bindParam(':details', $details);
            $stmt->bindParam(':ip', $ip);
            $stmt->execute();

            Helpers::sendResponse(true, 'Attendance record deleted successfully');
        } else {
            Helpers::sendResponse(false, 'Failed to delete attendance record', null, 500);
        }
    } else {
        Helpers::sendResponse(false, 'Method not allowed', null, 405);
    }
} catch (PDOException $e) {
    ErrorLogger::logDatabaseError($e, $userData['user_id'] ?? 'unknown', [
        'endpoint' => 'admin/attendance',
        'user_id' => $userData['user_id'] ?? 'unknown'
    ]);
    Helpers::sendResponse(false, 'Database error in attendance management: ' . $e->getMessage(), null, 500);
} catch (Exception $e) {
    ErrorLogger::logError($e, [
        'endpoint' => 'admin/attendance',
        'user_id' => $userData['user_id'] ?? 'unknown'
    ]);
    Helpers::sendResponse(false, 'Error in attendance management: ' . $e->getMessage(), null, 500);
}
