<?php

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class User {
    private $db;

    public function __construct(){
        // We will create an autoloader later, but for now, we assume Database class is available.
        // This line instantiates our database handler.
        $this->db = new Database;
    }

    // Find user by email
    public function findByEmail($email){
        $this->db->query('SELECT * FROM users WHERE email = :email');
        $this->db->bind(':email', $email);
        $row = $this->db->single();

        // Check if a row was returned
        if($this->db->rowCount() > 0){
            return $row;
        } else {
            return false;
        }
    }

    // Find user by username
    public function findByUsername($username){
        $this->db->query('SELECT * FROM users WHERE username = :username');
        $this->db->bind(':username', $username);
        $row = $this->db->single();

        // Check if a row was returned
        if($this->db->rowCount() > 0){
            return $row;
        } else {
            return false;
        }
    }

    // Find user by ID
    public function findById($id){
        $this->db->query('SELECT * FROM users WHERE id = :id');
        $this->db->bind(':id', $id);
        $row = $this->db->single();

        if($this->db->rowCount() > 0){
            return $row;
        } else {
            return false;
        }
    }

    // Update a user's role
    public function updateRole($user_id, $role){
        $this->db->query('UPDATE users SET role = :role WHERE id = :id');
        $this->db->bind(':role', $role);
        $this->db->bind(':id', $user_id);

        // Execute the query
        return $this->db->execute();
    }

    // Register a new user
    public function register($data){
        $this->db->query('INSERT INTO users (username, email, password_hash, first_name, last_name, phone_number, profile_picture) VALUES (:username, :email, :password_hash, :first_name, :last_name, :phone_number, :profile_picture)');
        
        // Bind values from the data array
        $this->db->bind(':username', $data['username']);
        $this->db->bind(':email', $data['email']);
        $this->db->bind(':password_hash', $data['password_hash']);
        $this->db->bind(':first_name', $data['first_name']);
        $this->db->bind(':last_name', $data['last_name']);
        $this->db->bind(':phone_number', $data['phone_number'] ?? null);
        $this->db->bind(':profile_picture', $data['profile_picture'] ?? null);

        // Execute the query
        return $this->db->execute();
    }

    // Get all users
    public function getAll(){
        $this->db->query('SELECT id, username, email, first_name, last_name, role, created_at FROM users ORDER BY created_at DESC');
        return $this->db->resultSet();
    }

    // Login user
    public function login($email, $password){
        $row = $this->findByEmail($email);

        if($row === false){
            return false; // User not found
        }

        $hashed_password = $row->password_hash;
        if(password_verify($password, $hashed_password)){
            return $row; // Password is correct, return user object
        } else {
            return false; // Password is not correct
        }
    }

    // Get users who can be assigned as managers
    public function getPotentialManagers($roles = ['league_manager', 'admin', 'super_admin']) {
        if (empty($roles)) {
            return [];
        }
        $placeholders = implode(',', array_fill(0, count($roles), '?'));
        $this->db->query("SELECT id, first_name, last_name, username FROM users WHERE role IN ($placeholders) ORDER BY last_name ASC");
        
        return $this->db->resultSet(array_values($roles));
    }

    // Get user ID from JWT token in Authorization header
    public function getUserIdFromToken() {
        $authHeader = null;
        // Check for the header in different server environments
        if (isset($_SERVER['Authorization'])) {
            $authHeader = $_SERVER['Authorization'];
        } elseif (isset($_SERVER['HTTP_AUTHORIZATION'])) { // Nginx or fast CGI
            $authHeader = $_SERVER['HTTP_AUTHORIZATION'];
        } elseif (function_exists('getallheaders')) {
            $headers = getallheaders();
            $authHeader = $headers['Authorization'] ?? null;
        }

        if (!$authHeader) {
            return null;
        }

        list($jwt) = sscanf($authHeader, 'Bearer %s');

        if (!$jwt) {
            return null;
        }

        try {
            $decoded = JWT::decode($jwt, new Key(JWT_KEY, 'HS256'));
            // The user ID should be in the 'sub' (subject) claim of our token
            if (isset($decoded->sub)) {
                return $decoded->sub;
            }
            // Fallback for older tokens that might have it in data->id
            return $decoded->data->id ?? null;
        } catch (Exception $e) {
            // Token is invalid
            return null;
        }
    }

    public function getUsersByRole($role) {
        $this->db->query('SELECT id, first_name, last_name FROM users WHERE role = :role ORDER BY first_name, last_name');
        $this->db->bind(':role', $role);

        $results = $this->db->resultSet();
        if($this->db->rowCount() > 0){
            return $results;
        }
        return false;
    }

    /**
     * Gets full user details for profile editing.
     * @param int $id The user ID.
     * @return object|null The user object or null if not found.
     */
    public function getFullUserDetailsById(int $id): ?object
    {
        $this->db->query('SELECT * FROM users WHERE id = :id');
        $this->db->bind(':id', $id);
        $row = $this->db->single();
        return $row ?: null;
    }

    /**
     * Updates a user's profile details.
     * @param array $data Associative array of user data.
     * @return bool True on success, false on failure.
     */
    public function updateProfile(array $data): bool
    {
        $sql = 'UPDATE users SET first_name = :first_name, last_name = :last_name, email = :email, username = :username';
        if (isset($data['profile_picture'])) {
            $sql .= ', profile_picture = :profile_picture';
        }
        $sql .= ' WHERE id = :id';

        $this->db->query($sql);
        $this->db->bind(':id', $data['id']);
        $this->db->bind(':first_name', $data['first_name']);
        $this->db->bind(':last_name', $data['last_name']);
        $this->db->bind(':email', $data['email']);
        $this->db->bind(':username', $data['username']);
        if (isset($data['profile_picture'])) {
            $this->db->bind(':profile_picture', $data['profile_picture']);
        }

        return $this->db->execute();
    }

    /**
     * Updates a user's password.
     * @param int $id The user ID.
     * @param string $new_password_hash The new hashed password.
     * @return bool True on success, false on failure.
     */
    public function updatePassword(int $id, string $new_password_hash): bool
    {
        $this->db->query('UPDATE users SET password_hash = :password_hash WHERE id = :id');
        $this->db->bind(':password_hash', $new_password_hash);
        $this->db->bind(':id', $id);
        return $this->db->execute();
    }

    /**
     * Search for users eligible to be hired (e.g., role is 'user' or 'fan').
     * @param string $query The search term.
     * @param int $limit The maximum number of results.
     * @return array An array of user objects.
     */
    public function searchEligibleStaff(string $query, int $limit = 10): array
    {
        $this->db->query("
            SELECT id, first_name, last_name, email, role 
            FROM users 
            WHERE (role = 'user' OR role = 'fan') AND (first_name LIKE :query1 OR last_name LIKE :query2 OR email LIKE :query3)
            LIMIT :limit
        ");
        $this->db->bind(':query1', '%' . $query . '%');
        $this->db->bind(':query2', '%' . $query . '%');
        $this->db->bind(':query3', '%' . $query . '%');
        $this->db->bind(':limit', $limit, PDO::PARAM_INT);
        return $this->db->resultSet();
    }

    /**
     * Get all users with a specific role.
     * @param string $role
     * @return array
     */
    public function getAllByRole(string $role): array {
        return $this->getUsersByRole($role) ?: [];
    }

    /**
     * Saves a push notification subscription to the database.
     * @param int $user_id The ID of the user.
     * @param array $subscription The subscription data from the Push API.
     * @return bool True on success, false on failure.
     */
    public function savePushSubscription(int $user_id, array $subscription): bool
    {
        $endpoint = $subscription['endpoint'] ?? null;
        $p256dh = $subscription['keys']['p256dh'] ?? null;
        $auth = $subscription['keys']['auth'] ?? null;

        if (!$endpoint || !$p256dh || !$auth) {
            return false;
        }

        $this->db->query("INSERT INTO push_subscriptions (user_id, endpoint, p256dh_key, auth_key) VALUES (:user_id, :endpoint, :p256dh, :auth) ON DUPLICATE KEY UPDATE user_id = VALUES(user_id), p256dh_key = VALUES(p256dh_key), auth_key = VALUES(auth_key)");
        $this->db->bind(':user_id', $user_id);
        $this->db->bind(':endpoint', $endpoint);
        $this->db->bind(':p256dh', $p256dh);
        $this->db->bind(':auth', $auth);

        return $this->db->execute();
    }

    /**
     * Removes a push notification subscription from the database.
     * @param int $user_id The ID of the user.
     * @param string $endpoint The subscription endpoint to remove.
     * @return bool True on success, false on failure.
     */
    public function removePushSubscription(int $user_id, string $endpoint): bool
    {
        $this->db->query("DELETE FROM push_subscriptions WHERE user_id = :user_id AND endpoint = :endpoint");
        $this->db->bind(':user_id', $user_id);
        $this->db->bind(':endpoint', $endpoint);
        return $this->db->execute();
    }
}
?>