<?php
// controllers/UserController.php

/**
 * UserController for Rehlko Customer Care application.
 * Manages user-related operations, including CRUD by admins and profile updates by users themselves.
 */
class UserController {
    private $conn;
    private $userModel;
    private $mailer;
    private $notificationModel;

    /**
     * Constructor for UserController.
     *
     * @param mysqli $db The database connection object.
     */
    public function __construct($db) {
        $this->conn = $db;
        $this->userModel = new User($db);
        $this->mailer = new Mailer();
        $this->notificationModel = new Notification($db);
    }

    /**
     * Creates a new user.
     * Only 'superadmin' and 'admin' roles are authorized.
     */
    public function create() {
        // Check authorization
        $currentUserRole = getCurrentUserRole();
        if (!in_array($currentUserRole, ['superadmin', 'admin'])) {
            sendJsonResponse(['message' => 'Unauthorized. Only superadmin or admin can create users.'], 403);
            return;
        }

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

        // Validate required fields
        if (empty($data->username) || empty($data->email) || empty($data->password) || empty($data->role) || empty($data->country_id)) {
            sendJsonResponse(['message' => 'Missing required fields: username, email, password, role, country_id.'], 400);
            return;
        }

        // Check if email already exists
        if ($this->userModel->emailExists($data->email)) {
            $exist_email_user = $this->userModel->findByEmailorUsername($data->email);
            if ($exist_email_user && $exist_email_user['is_active'] == 0) {
                // If a user with the same email exists but is inactive, revive them.
                $id = $exist_email_user['id'];
                
                $this->userModel->id = $id; // Set ID for update
                $this->userModel->username = $data->username;
                $this->userModel->fullname = $data->fullname ?? $data->username;
                $this->userModel->email = $data->email;
                $this->userModel->password = $data->password;
                $this->userModel->role = $data->role;
                $this->userModel->country_id = $data->country_id;
                $this->userModel->phone = $data->phone ?? null;
                $this->userModel->address = $data->address ?? null;
                
                if ($this->userModel->reviveUser($id, true)) {
                    // Send welcome email and in-app notification
                    $this->sendWelcomeCommunication($this->userModel);
                    sendJsonResponse(['message' => 'User created successfully.', 'userId' => $this->userModel->id], 201);
                } else {
                    sendJsonResponse(['message' => 'Failed to revive user.'], 500);
                }
            } else {
                sendJsonResponse(['message' => 'User with this email already exists.'], 409);
            }
            return;
        }

        // Set user properties from request data
        $this->userModel->username = $data->username;
        $this->userModel->fullname = $data->fullname ?? $data->username;
        $this->userModel->email = $data->email;
        $this->userModel->password = $data->password;
        $this->userModel->role = $data->role;
        $this->userModel->country_id = $data->country_id;
        $this->userModel->phone = $data->phone ?? null;
        $this->userModel->address = $data->address ?? null;
        $this->userModel->is_active = 1; // Explicitly set as active for new users.
        $this->userModel->company_id = $data->company_id;
       if ($this->userModel->create()) {
          $this->sendWelcomeCommunication($this->userModel);
            sendJsonResponse(['message' => 'User created successfully.', 'userId' => $this->userModel->id], 201);
        } else {
            sendJsonResponse(['message' => 'Failed to create user.'], 500);
        }
    }

    /**
     * Reads all users.
     * Access is restricted based on role (superadmin, admin can see all; others see limited sets).
     */
    public function readAll() {
        $result = $this->userModel->readAll();

        if ($result) {
            $users_arr = [];
            while ($row = $result->fetch_assoc()) {
                unset($row['password']);
                $users_arr[] = $row;
            }
            sendJsonResponse(['message' => 'Users fetched successfully.', 'data' => $users_arr], 200);
        } else {
            sendJsonResponse(['message' => 'Failed to retrieve users or unauthorized.'], 403);
        }
    }

    /**
     * Reads a single user by ID.
     * Access is restricted based on role and relationship (self, support team).
     *
     * @param int $id The ID of the user to retrieve.
     */
    public function read($id) {
        $this->userModel->id = $id;
        $user = $this->userModel->readOne();

        if ($user) {
            unset($user['password']);
            sendJsonResponse($user);
        } else {
            sendJsonResponse(['message' => 'User not found.'], 404);
        }
    }

    /**
     * Updates an existing user.
     * Only 'superadmin' and 'admin' roles can update other users.
     */
    public function update($id) {
        $currentUserRole = getCurrentUserRole();
        if (!in_array($currentUserRole, ['superadmin', 'admin'])) {
            sendJsonResponse(['message' => 'Unauthorized. Only superadmin or admin can update users.'], 403);
            return;
        }
        
        $data = json_decode(file_get_contents("php://input"), true);

        if (empty($data)) {
            sendJsonResponse(['message' => 'No fields provided for update.'], 400);
            return;
        }
        //error_log(print_r($data,true));
        $this->userModel->id = $id;
        $existingUserData = $this->userModel->readOne();
        if (!$existingUserData) {
            sendJsonResponse(['message' => 'User not found.'], 404);
            return;
        }

        if (isset($data['username'])) {
            $this->userModel->username = $data['username'];
        }
        if (isset($data['fullname'])) {
            $this->userModel->fullname = $data['fullname'];
        }
        if (isset($data['email'])) {
            if ($data['email'] !== $existingUserData['email']) {
                if ($this->userModel->emailExists($data['email'], $id)) {
                    sendJsonResponse(['message' => 'Another user with this email already exists.'], 409);
                    return;
                }
            }
            $this->userModel->email = $data['email'];
        }
        if (isset($data['role'])) {
            $this->userModel->role = $data['role'];
        }
        if (isset($data['phone'])) {
            $this->userModel->phone = $data['phone'];
        }
        if (isset($data['address'])) {
            $this->userModel->address = $data['address'];
        }
        if (isset($data['country_id'])) {
            $this->userModel->country_id = $data['country_id'];
        }
        if (isset($data['company_id'])) {
            $this->userModel->company_id = $data['company_id'];
        }
        
        // Handle password update for admin
        if(isset($data['password']) && !empty($data['password'])){
            $this->userModel->password = $data['password'];
            if (!$this->userModel->updatePassword($id, hashPassword($data['password']))) {
                 sendJsonResponse(['message' => 'Failed to update password.'], 500);
                 return;
            }
        }

        if ($this->userModel->update()) {
            error_log('User updated successfully. User Role: ' . $this->userModel->role . ', User Data : ' . $this->userModel->country_id);
            sendJsonResponse(['message' => 'User updated successfully.'], 200);
        } else {
            sendJsonResponse(['message' => 'Failed to update user.'], 500);
        }
    }

    /**
     * Allows a user to update their own profile.
     * Authenticated user can update their own data.
     *
     * @param int $id The ID of the user whose profile is being updated.
     */
    public function updateProfile($id) {
        $currentUserId = getCurrentUserId();
        if ($currentUserId != $id) {
            sendJsonResponse(['message' => 'Unauthorized. You can only update your own profile.'], 403);
            return;
        }

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

        if (empty($data)) {
            sendJsonResponse(['message' => 'No fields provided for update.'], 400);
            return;
        }
        
       

        $existingUserData = $this->userModel->readById($id);
        if (!$existingUserData) {
            sendJsonResponse(['message' => 'User not found or an error occurred.'], 404);
            return;
        }

        // Handle Password Update
        if (isset($data['new_password']) && !empty($data['new_password'])) {
            if (isset($data['current_password']) && !empty($data['current_password'])) {
                if (verifyPassword($data['current_password'], $existingUserData['password'])) {
                    $newHashedPassword = hashPassword($data['new_password']);
                    if (!$this->userModel->updatePassword($id, $newHashedPassword)) {
                        error_log("Failed to update password for user ID: $id");
                        sendJsonResponse(['message' => 'Failed to update password. Please try again.'], 500);
                        return;
                    }
                    unset($data['current_password']);
                    unset($data['new_password']);
                } else {
                    sendJsonResponse(['message' => 'Current password incorrect.'], 401);
                    return;
                }
            } else {
                sendJsonResponse(['message' => 'Current password is required to change password.'], 400);
                return;
            }
        }

        // Check for email conflict
        
        if (isset($data['email'])) {
            if ($data['email'] !== $existingUserData['email']) {
                if ($this->userModel->emailExists($data['email'], $id)) {
                    sendJsonResponse(['message' => 'Another user with this email already exists.'], 409);
                    return;
                }
            }
            $this->userModel->email = $data['email'];
        }
        
        if (isset($data['username'])) {
            if ($data['username'] !== $existingUserData['username']) {
                if ($this->userModel->usernameExists($data['username'], $id)) {
                    sendJsonResponse(['message' => 'Another user with this username already exists.'], 409);
                    return;
                }
            }
            $this->userModel->username = $data['username'];
        }
        
       

        // Assign other fields
        if (isset($data['fullname'])) {
            $this->userModel->fullname = $data['fullname'];
        }
        if (isset($data['phone'])) {
            $this->userModel->phone = $data['phone'];
        }
        if (isset($data['address'])) {
            $this->userModel->address = $data['address'];
        }
        if (isset($data['country_id'])) {
            $countryId = $data['country_id'];
            if ($countryId !== null) {
                if (!is_numeric($countryId) || $countryId <= 0) {
                    sendJsonResponse(['message' => 'Invalid Country ID format.'], 400);
                    return;
                }
                $countryId = (int)$countryId;
                if (!$this->userModel->countryExists($countryId)) {
                    sendJsonResponse(['message' => 'Provided Country ID does not exist.'], 400);
                    return;
                }
            }
            $this->userModel->country_id = $countryId;
        }

        // Set the ID for the model's update method
        $this->userModel->id = $id;

        if ($this->userModel->updateProfile()) {
            sendJsonResponse(['message' => 'Profile updated successfully.'], 200);
        } else {
            sendJsonResponse(['message' => 'Failed to update profile. Please try again.'], 500);
        }
    }

    /**
     * Saves a user's device token for push notifications.
     * The token is associated with the currently authenticated user.
     */
    public function saveDeviceToken() {
        $currentUserId = getCurrentUserId();
        if (!$currentUserId) {
            sendJsonResponse(['message' => 'Unauthorized. Please log in.'], 401);
            return;
        }

        $data = json_decode(file_get_contents("php://input"));
        if (empty($data->device_token)) {
            sendJsonResponse(['message' => 'Missing required field: device_token.'], 400);
            return;
        }

        $deviceToken = $data->device_token;
        $this->userModel->id = $currentUserId;

        if ($this->userModel->saveDeviceToken($deviceToken)) {
            sendJsonResponse(['message' => 'Device token saved successfully.'], 200);
        } else {
            sendJsonResponse(['message' => 'Failed to save device token.'], 500);
        }
    }

    /**
     * Deletes a user.
     * Only 'superadmin' and 'admin' roles are authorized.
     *
     * @param int $id The ID of the user to delete.
     */
    public function delete($id) {
        $currentUserRole = getCurrentUserRole();
        if (!in_array($currentUserRole, ['superadmin', 'admin'])) {
            sendJsonResponse(['message' => 'Unauthorized. Only superadmin or admin can delete users.'], 403);
            return;
        }

        $currentUserId = getCurrentUserId();
        if ($currentUserId == $id) {
            sendJsonResponse(['message' => 'You cannot delete your own account.'], 403);
            return;
        }

        $this->userModel->id = $id;

        if ($this->userModel->delete()) {
            sendJsonResponse(['message' => 'User deleted successfully.'], 200);
        } else {
            sendJsonResponse(['message' => 'Failed to delete user or user not found.'], 500);
        }
    }
    
    public function active($id) {
        $currentUserRole = getCurrentUserRole();
        if (!in_array($currentUserRole, ['superadmin', 'admin'])) {
            sendJsonResponse(['message' => 'Unauthorized. Only superadmin or admin can delete users.'], 403);
            return;
        }

        $currentUserId = getCurrentUserId();
        if ($currentUserId == $id) {
            sendJsonResponse(['message' => 'You cannot delete your own account.'], 403);
            return;
        }

        $this->userModel->id = $id;

        if ($this->userModel->active()) {
            sendJsonResponse(['message' => 'User activation successfully.'], 200);
        } else {
            sendJsonResponse(['message' => 'Failed to activate user or user not found.'], 500);
        }
    }
    
    public function deactive($id) {
        $currentUserRole = getCurrentUserRole();
        if (!in_array($currentUserRole, ['superadmin', 'admin'])) {
            sendJsonResponse(['message' => 'Unauthorized. Only superadmin or admin can delete users.'], 403);
            return;
        }

        $currentUserId = getCurrentUserId();
        if ($currentUserId == $id) {
            sendJsonResponse(['message' => 'You cannot delete your own account.'], 403);
            return;
        }

        $this->userModel->id = $id;

        if ($this->userModel->deactive()) {
            sendJsonResponse(['message' => 'User deactivation successfully.'], 200);
        } else {
            sendJsonResponse(['message' => 'Failed to deactivate user or user not found.'], 500);
        }
    }
    
    /**
     * Helper function to send welcome email and in-app notification.
     * @param object $userModel The user model object.
     */
    private function sendWelcomeCommunication($userModel) {
        $welcomeEmailBody = $this->mailer->getEmailTemplate('welcome_user', [
            'fullname' => $userModel->fullname,
            'username' => $userModel->username,
            'email' => $userModel->email,
            'temp_password' => $userModel->password, // A temp password or reset link should be used in production.
            'role' => $userModel->role,
            'login_link' => APP_BASE_URL . '/login'
        ]);

        $this->mailer->sendMail(
            $userModel->email,
            $userModel->fullname,
            'Welcome to Rehlko Customer Care',
            $welcomeEmailBody
        );

        $this->notificationModel->createNotification(
            $userModel->id,
            'Welcome to Rehlko Customer Care!',
            'Your account has been successfully created. You can now log in.',
            'users'
        );
    }
}