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

try {

    header('Content-Type: application/json');

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

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

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

    // Verify admin access
    $query = "SELECT ur.role_level, ur.can_manage_users 
              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['can_manage_users']) {
        Helpers::sendResponse(false, 'Unauthorized. User management access required.', null, 403);
    }

    $method = $_SERVER['REQUEST_METHOD'];

    switch ($method) {
        case 'GET':
            handleGet($db, $userData);
            break;
        case 'POST':
            handleCreate($db, $userData);
            break;
        case 'PUT':
            handleUpdate($db, $userData);
            break;
        case 'DELETE':
            handleDelete($db, $userData);
            break;
        default:
            Helpers::sendResponse(false, 'Method not allowed', null, 405);
    }
} catch (PDOException $e) {
    ErrorLogger::logDatabaseError($e, $userData['user_id'] ?? 'unknown', [
        'endpoint' => 'admin/users',
        'user_id' => $userData['user_id'] ?? 'unknown'
    ]);
    Helpers::sendResponse(false, 'Database error in users management: ' . $e->getMessage(), null, 500);
} catch (Exception $e) {
    ErrorLogger::logError($e, [
        'endpoint' => 'admin/users',
        'user_id' => $userData['user_id'] ?? 'unknown'
    ]);
    Helpers::sendResponse(false, 'Error in users management: ' . $e->getMessage(), null, 500);
}

function handleGet($db, $userData)
{
    // Get single user or list all users
    $userId = $_GET['id'] ?? null;

    if ($userId) {
        // Get single user with full details
        $query = "SELECT u.id, u.email, u.first_name, u.last_name, u.avatar_url, 
                         u.phone_number, u.gender, u.is_hod, u.is_active, u.is_verified,
                         u.last_login, u.created_at, u.updated_at,
                         ur.id as role_id, ur.role_name, ur.role_level,
                         d.id as department_id, d.name as department_name
                  FROM users u
                  JOIN user_roles ur ON u.role_id = ur.id
                  LEFT JOIN departments d ON u.department_id = d.id
                  WHERE u.id = :user_id";

        $stmt = $db->prepare($query);
        $stmt->bindParam(':user_id', $userId);
        $stmt->execute();
        $user = $stmt->fetch(PDO::FETCH_ASSOC);

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

        // Get user's attendance statistics
        $query = "SELECT 
                    COUNT(*) as total_attendance,
                    COUNT(CASE WHEN MONTH(clock_in_time) = MONTH(CURDATE()) THEN 1 END) as month_attendance,
                    COUNT(CASE WHEN YEARWEEK(clock_in_time, 1) = YEARWEEK(CURDATE(), 1) THEN 1 END) as week_attendance,
                    SUM(time_spent) as total_minutes
                  FROM attendance
                  WHERE user_id = :user_id AND is_valid = TRUE";

        $stmt = $db->prepare($query);
        $stmt->bindParam(':user_id', $userId);
        $stmt->execute();
        $stats = $stmt->fetch(PDO::FETCH_ASSOC);

        // Get user's tickets
        $query = "SELECT COUNT(*) as total_tickets,
                         COUNT(CASE WHEN is_resolved = FALSE THEN 1 END) as unresolved_tickets
                  FROM tickets
                  WHERE user_id = :user_id";

        $stmt = $db->prepare($query);
        $stmt->bindParam(':user_id', $userId);
        $stmt->execute();
        $tickets = $stmt->fetch(PDO::FETCH_ASSOC);

        // Get user's rewards
        $query = "SELECT COUNT(*) as total_rewards,
                         COUNT(CASE WHEN is_redeemed = FALSE THEN 1 END) as unredeemed_rewards
                  FROM users_service_rewards
                  WHERE user_id = :user_id";

        $stmt = $db->prepare($query);
        $stmt->bindParam(':user_id', $userId);
        $stmt->execute();
        $rewards = $stmt->fetch(PDO::FETCH_ASSOC);

        $user['statistics'] = [
            'attendance' => $stats,
            'tickets' => $tickets,
            'rewards' => $rewards
        ];

        Helpers::sendResponse(true, 'User retrieved successfully', $user);
    } else {
        // Get all users with filters
        $page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
        $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 20;
        $offset = ($page - 1) * $limit;

        $search = $_GET['search'] ?? '';
        $roleId = $_GET['role_id'] ?? null;
        $departmentId = $_GET['department_id'] ?? null;
        $isActive = isset($_GET['is_active']) ? (bool)$_GET['is_active'] : null;
        $isVerified = isset($_GET['is_verified']) ? (bool)$_GET['is_verified'] : null;

        // Build query with filters
        $whereConditions = [];
        $params = [];

        if ($search) {
            $whereConditions[] = "(u.first_name LIKE :search OR u.last_name LIKE :search OR u.email LIKE :search OR u.phone_number LIKE :search)";
            $params[':search'] = "%$search%";
        }

        if ($roleId) {
            $whereConditions[] = "u.role_id = :role_id";
            $params[':role_id'] = $roleId;
        }

        if ($departmentId) {
            $whereConditions[] = "u.department_id = :department_id";
            $params[':department_id'] = $departmentId;
        }

        if ($isActive !== null) {
            $whereConditions[] = "u.is_active = :is_active";
            $params[':is_active'] = $isActive ? 1 : 0;
        }

        if ($isVerified !== null) {
            $whereConditions[] = "u.is_verified = :is_verified";
            $params[':is_verified'] = $isVerified ? 1 : 0;
        }

        // HOD can only see users in their department
        if ($userData['role'] === 'hod' && $userData['department_id']) {
            $whereConditions[] = "u.department_id = :user_dept";
            $params[':user_dept'] = $userData['department_id'];
        }

        $whereClause = !empty($whereConditions) ? 'WHERE ' . implode(' AND ', $whereConditions) : '';

        // Get total count
        $countQuery = "SELECT COUNT(*) as total FROM users u $whereClause";
        $stmt = $db->prepare($countQuery);
        foreach ($params as $key => $value) {
            $stmt->bindValue($key, $value);
        }
        $stmt->execute();
        $totalRecords = $stmt->fetch(PDO::FETCH_ASSOC)['total'];

        // Get users
        $query = "SELECT u.id, u.email, u.first_name, u.last_name, u.avatar_url,
                         u.phone_number, u.gender, u.is_hod, u.is_active, u.is_verified,
                         u.last_login, u.created_at,
                         ur.role_name, ur.role_level,
                         d.name as department_name
                  FROM users u
                  JOIN user_roles ur ON u.role_id = ur.id
                  LEFT JOIN departments d ON u.department_id = d.id
                  $whereClause
                  ORDER BY u.created_at 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();
        $users = $stmt->fetchAll(PDO::FETCH_ASSOC);

        Helpers::sendResponse(true, 'Users retrieved successfully', [
            'users' => $users,
            'pagination' => [
                'total' => (int)$totalRecords,
                'page' => $page,
                'limit' => $limit,
                'total_pages' => ceil($totalRecords / $limit)
            ]
        ]);
    }
}

function handleCreate($db, $userData)
{
    // Only admins and superadmins can create users
    if (!in_array($userData['role'], ['admin', 'superadmin'])) {
        Helpers::sendResponse(false, 'Unauthorized. Admin access required.', null, 403);
    }

    $data = json_decode(file_get_contents('php://input'), true);

    // Validate required fields
    $requiredFields = ['email', 'first_name', 'last_name', 'role'];
    foreach ($requiredFields as $field) {
        if (empty($data[$field])) {
            Helpers::sendResponse(false, "Field '$field' is required", null, 400);
        }
    }

    // Validate email format
    if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
        Helpers::sendResponse(false, 'Invalid email format', null, 400);
    }

    // Check if email already exists
    $query = "SELECT id FROM users WHERE email = :email";
    $stmt = $db->prepare($query);
    $stmt->bindParam(':email', $data['email']);
    $stmt->execute();

    if ($stmt->rowCount() > 0) {
        Helpers::sendResponse(false, 'Email already exists', null, 409);
    }

    // Validate role exists
    $query = "SELECT `role_name` FROM `user_roles` WHERE `id` = :role";
    $stmt = $db->prepare($query);
    $stmt->bindParam(':role', $data['role']);
    $stmt->execute();
    $role = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$role) {
        Helpers::sendResponse(false, 'Invalid role', null, 400);
    }

    // Validate department if provided
    if (!empty($data['department'])) {
        $query = "SELECT `id` FROM `departments` WHERE `id` = :dept_id AND `is_active` = TRUE";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':dept_id', $data['department']);
        $stmt->execute();

        if ($stmt->rowCount() === 0) {
            Helpers::sendResponse(false, 'Invalid department', null, 400);
        }
    }

    // Hash password
    $password = '123@Password';
    if (!isset($data->password)) {
        $data["password"] = $password;
    }
    $hashedPassword = password_hash($data["password"], PASSWORD_BCRYPT);

    // Generate verification code
    $verificationCode = str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT);
    $verificationExpires = date('Y-m-d H:i:s', strtotime('+24 hours'));

    // Insert user
    $query = "INSERT INTO `users` (`email`, `first_name`, `last_name`, `phone_number`, `gender`, 
                                  `password`, `role_id`, `department_id`, `is_hod`, `is_active`, 
                                  `verification_code`, `verification_expires`, `avatar_url`)
              VALUES (:email, :first_name, :last_name, :phone_number, :gender,
                      :password, :role, :department, :is_hod, :is_active,
                      :verification_code, :verification_expires, :avatar_url)";

    $stmt = $db->prepare($query);
    $stmt->bindParam(':email', $data['email']);
    $stmt->bindParam(':first_name', $data['first_name']);
    $stmt->bindParam(':last_name', $data['last_name']);
    $stmt->bindParam(':phone_number', $data['phone_number']);
    $stmt->bindParam(':gender', $data['gender']);
    $stmt->bindParam(':password', $hashedPassword);
    $stmt->bindParam(':role', $data['role']);
    $stmt->bindParam(':department', $data['department']);
    $isHod = isset($data['is_hod']) ? (int)$data['is_hod'] : 0;
    $stmt->bindParam(':is_hod', $isHod, PDO::PARAM_INT);
    $isActive = isset($data['is_active']) ? (int)$data['is_active'] : 1;
    $stmt->bindParam(':is_active', $isActive, PDO::PARAM_INT);
    $stmt->bindParam(':verification_code', $verificationCode);
    $stmt->bindParam(':verification_expires', $verificationExpires);
    $avatarUrl = isset($data['avatar_url']) ? (string)$data['avatar_url'] : null;
    $stmt->bindParam(':avatar_url', $avatarUrl);

    $stmt->execute();
    $userId = $db->lastInsertId();

    // Log admin action
    logAdminAction(
        $db,
        $userData['user_id'],
        'create new user',
        'create',
        'user',
        $userId,
        json_encode([
            'email' => $data['email'],
            'role' => $role['role_name']
        ])
    );

    // TODO: Send verification email with code

    Helpers::sendResponse(true, 'User created successfully', [
        'user_id' => $userId,
        'verification_code' => $verificationCode
    ], 201);
}

function handleUpdate($db, $userData)
{
    $data = json_decode(file_get_contents('php://input'), true);

    if (empty($data['id'])) {
        Helpers::sendResponse(false, 'User ID is required', null, 400);
    }

    $userId = $data['id'];

    // Check if user exists
    $query = "SELECT u.*, ur.role_name 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', $userId);
    $stmt->execute();
    $existingUser = $stmt->fetch(PDO::FETCH_ASSOC);

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

    // HOD can only update users in their department
    if ($userData['role'] === 'hod') {
        if ($existingUser['department_id'] != $userData['department_id']) {
            Helpers::sendResponse(false, 'Unauthorized to update this user', null, 403);
        }
    }

    // Build update query dynamically
    $updateFields = [];
    $params = [':user_id' => $userId];

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

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

    if (isset($data['email'])) {
        // Check if email is already taken by another user
        $query = "SELECT id FROM users WHERE email = :email AND id != :user_id";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':email', $data['email']);
        $stmt->bindParam(':user_id', $userId);
        $stmt->execute();

        if ($stmt->rowCount() > 0) {
            Helpers::sendResponse(false, 'Email already exists', null, 409);
        }

        $updateFields[] = "email = :email";
        $params[':email'] = $data['email'];
    }

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

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

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

    // Only admins can update role, department, and status
    if (in_array($userData['role'], ['admin', 'superadmin'])) {
        if (isset($data['role_id'])) {
            $updateFields[] = "role_id = :role_id";
            $params[':role_id'] = $data['role_id'];
        }

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

        if (isset($data['is_hod'])) {
            $updateFields[] = "is_hod = :is_hod";
            $params[':is_hod'] = (int)$data['is_hod'];
        }

        if (isset($data['is_active'])) {
            $updateFields[] = "is_active = :is_active";
            $params[':is_active'] = (int)$data['is_active'];
        }

        if (isset($data['is_verified'])) {
            $updateFields[] = "is_verified = :is_verified";
            $params[':is_verified'] = (int)$data['is_verified'];
        }
    }

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

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

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

    $stmt->execute();

    // Log admin action
    Helpers::logAdminAction(
        $db,
        $userData['user_id'],
        'create new user',
        'create',
        'user',
        $userId,
        json_encode([
            'email' => $data['email'],
            'role' => $data['role_id']
        ])
    );

    Helpers::sendResponse(true, 'User updated successfully');
}

function handleDelete($db, $userData)
{
    // Only superadmins can delete users
    if ($userData['role'] !== 'superadmin') {
        Helpers::sendResponse(false, 'Unauthorized. Superadmin access required.', null, 403);
    }

    $data = json_decode(file_get_contents('php://input'), true);

    // Delete a user
    // Get user id from URL as a parameter
    $userId = isset($data->user) ? intval($data->user) : null;

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

    // Prevent admin from deleting themselves
    if ($userId === $userData['user_id']) {
        Helpers::sendResponse(false, 'You cannot delete your own account', null, 400);
    }

    $userDetailsQuery = "SELECT * FROM users WHERE id = :user_id";
    $userDetailsStmt = $db->prepare($userDetailsQuery);
    $userDetailsStmt->bindValue(":user_id", $userId);
    $userDetailsStmt->execute();
    $userDetailsData = $userDetailsStmt->fetch(PDO::FETCH_ASSOC);

    if (!$userDetailsData) {
        Helpers::sendResponse(false, "Unfortunately, this user cannot be found in database", null, 0);
    }

    $query = "DELETE FROM `users` WHERE `id` = :user_id";
    $stmt = $db->prepare($query);
    $stmt->bindParam(':user_id', $userId);

    if ($stmt->execute()) {
        // Log admin activity
        $userFullName = $userDetailsData['first_name'] . ' ' . $userDetailsData['last_name'];
        logAdminAction(
            $db,
            $userData['user_id'],
            'delete user',
            'delete',
            'users',
            $userId,
            $userFullName
        );
        Helpers::sendResponse(true, 'User deleted successfully');
    } else {
        Helpers::sendResponse(false, 'Failed to delete user', null, 500);
    }
}

function logAdminAction($db, $adminId, $action, $actionType, $targetType, $targetId = null, $details = null)
{
    $query = "INSERT INTO admin_logs (admin_id, action, action_type, target_type, target_id, details, ip_address, created_at) 
                VALUES (:admin_id, :action, :action_type, :target_type, :target_id, :details, :ip_address, NOW())";

    $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';

    $stmt = $db->prepare($query);
    $stmt->bindParam(':admin_id', $adminId);
    $stmt->bindParam(':action', $action);
    $stmt->bindParam(':action_type', $actionType);
    $stmt->bindParam(':target_type', $targetType);
    $stmt->bindParam(':target_id', $targetId);
    $stmt->bindParam(':details', $details);
    $stmt->bindParam(':ip_address', $ip);
    $stmt->execute();
}
