<?php

/**
 * User Model
 * Handles user authentication and management
 */
class User {
    
    private $db;
    
    public $id;
    public $username;
    public $email;
    public $password_hash;
    public $is_active;
    public $created_at;
    public $updated_at;
    
    public function __construct() {
        $this->db = Database::getInstance();
    }
    
    /**
     * Authenticate user with username and password
     * 
     * @param string $username
     * @param string $password
     * @return User|false Returns User object on success, false on failure
     */
    public function authenticate($username, $password) {
        $sql = "SELECT * FROM users WHERE username = ? AND is_active = 1 LIMIT 1";
        $user = $this->db->fetchOne($sql, [$username]);
        
        if ($user && password_verify($password, $user['password_hash'])) {
            $this->fillFromArray($user);
            return $this;
        }
        
        return false;
    }
    
    /**
     * Create a new session for the user
     * 
     * @return string Session ID
     */
    public function createSession() {
        // Set session variables - persistent until manual logout
        $_SESSION['user_id'] = $this->id;
        $_SESSION['username'] = $this->username;
        
        // Regenerate session ID for security
        session_regenerate_id(true);
        
        return session_id();
    }
    
    /**
     * Validate if a session is active
     * 
     * @param int $userId
     * @return bool
     */
    public function validateSession($userId) {
        if (!isset($_SESSION['user_id']) || $_SESSION['user_id'] != $userId) {
            return false;
        }
        
        return true;
    }
    
    /**
     * Destroy user session (logout)
     * 
     * @return bool
     */
    public function destroySession() {
        // Clear session variables
        $_SESSION = [];
        
        // Destroy session cookie
        if (isset($_COOKIE[session_name()])) {
            setcookie(session_name(), '', time() - 3600, '/');
        }
        
        // Destroy session
        session_destroy();
        
        return true;
    }
    
    /**
     * Find user by ID
     * 
     * @param int $id
     * @return User|false
     */
    public function findById($id) {
        $sql = "SELECT * FROM users WHERE id = ? LIMIT 1";
        $user = $this->db->fetchOne($sql, [$id]);
        
        if ($user) {
            $this->fillFromArray($user);
            return $this;
        }
        
        return false;
    }
    
    /**
     * Find user by username
     * 
     * @param string $username
     * @return User|false
     */
    public function findByUsername($username) {
        $sql = "SELECT * FROM users WHERE username = ? LIMIT 1";
        $user = $this->db->fetchOne($sql, [$username]);
        
        if ($user) {
            $this->fillFromArray($user);
            return $this;
        }
        
        return false;
    }
    
    /**
     * Find user by email
     * 
     * @param string $email
     * @return User|false
     */
    public function findByEmail($email) {
        $sql = "SELECT * FROM users WHERE email = ? LIMIT 1";
        $user = $this->db->fetchOne($sql, [$email]);
        
        if ($user) {
            $this->fillFromArray($user);
            return $this;
        }
        
        return false;
    }
    
    /**
     * Create a new user
     * 
     * @param array $data
     * @return int|false User ID on success, false on failure
     */
    public function create($data) {
        // Validate required fields
        if (empty($data['username']) || empty($data['password']) || empty($data['email'])) {
            return false;
        }
        
        // Check if username already exists
        if ($this->findByUsername($data['username'])) {
            return false;
        }
        
        // Check if email already exists
        if ($this->findByEmail($data['email'])) {
            return false;
        }
        
        // Hash password
        $passwordHash = password_hash($data['password'], PASSWORD_DEFAULT);
        
        // Insert user
        $sql = "INSERT INTO users (username, password_hash, email, is_active) VALUES (?, ?, ?, ?)";
        $isActive = isset($data['is_active']) ? $data['is_active'] : 1;
        
        $this->db->execute($sql, [
            $data['username'],
            $passwordHash,
            $data['email'],
            $isActive
        ]);
        
        return $this->db->lastInsertId();
    }
    
    /**
     * Update user
     * 
     * @param int $id
     * @param array $data
     * @return bool
     */
    public function update($id, $data) {
        $fields = [];
        $values = [];
        
        // Build update query dynamically
        if (isset($data['username'])) {
            $fields[] = "username = ?";
            $values[] = $data['username'];
        }
        
        if (isset($data['email'])) {
            $fields[] = "email = ?";
            $values[] = $data['email'];
        }
        
        if (isset($data['password'])) {
            $fields[] = "password_hash = ?";
            $values[] = password_hash($data['password'], PASSWORD_DEFAULT);
        }
        
        if (isset($data['is_active'])) {
            $fields[] = "is_active = ?";
            $values[] = $data['is_active'];
        }
        
        if (empty($fields)) {
            return false;
        }
        
        $values[] = $id;
        $sql = "UPDATE users SET " . implode(', ', $fields) . " WHERE id = ?";
        
        return $this->db->execute($sql, $values) > 0;
    }
    
    /**
     * Delete user
     * 
     * @param int $id
     * @return bool
     */
    public function delete($id) {
        $sql = "DELETE FROM users WHERE id = ?";
        return $this->db->execute($sql, [$id]) > 0;
    }
    
    /**
     * Get all users
     * 
     * @return array
     */
    public function getAll() {
        $sql = "SELECT id, username, email, is_active, created_at, updated_at FROM users ORDER BY created_at DESC";
        return $this->db->fetchAll($sql);
    }
    
    /**
     * Get active users
     * 
     * @return array
     */
    public function getActive() {
        $sql = "SELECT id, username, email, created_at FROM users WHERE is_active = 1 ORDER BY username ASC";
        return $this->db->fetchAll($sql);
    }
    
    /**
     * Change password
     * 
     * @param int $userId
     * @param string $oldPassword
     * @param string $newPassword
     * @return bool
     */
    public function changePassword($userId, $oldPassword, $newPassword) {
        // Get user
        $user = $this->findById($userId);
        if (!$user) {
            return false;
        }
        
        // Verify old password
        if (!password_verify($oldPassword, $this->password_hash)) {
            return false;
        }
        
        // Update password
        $passwordHash = password_hash($newPassword, PASSWORD_DEFAULT);
        $sql = "UPDATE users SET password_hash = ? WHERE id = ?";
        
        return $this->db->execute($sql, [$passwordHash, $userId]) > 0;
    }
    
    /**
     * Fill object properties from array
     * 
     * @param array $data
     */
    private function fillFromArray($data) {
        $this->id = $data['id'] ?? null;
        $this->username = $data['username'] ?? null;
        $this->email = $data['email'] ?? null;
        $this->password_hash = $data['password_hash'] ?? null;
        $this->is_active = $data['is_active'] ?? null;
        $this->created_at = $data['created_at'] ?? null;
        $this->updated_at = $data['updated_at'] ?? null;
    }
    
    /**
     * Convert user to array (without sensitive data)
     * 
     * @return array
     */
    public function toArray() {
        return [
            'id' => $this->id,
            'username' => $this->username,
            'email' => $this->email,
            'is_active' => $this->is_active,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at
        ];
    }
    
    /**
     * Get paginated users
     */
    public function getPaginated($limit = 10, $offset = 0) {
        $sql = "SELECT * FROM users ORDER BY created_at DESC LIMIT ? OFFSET ?";
        return $this->db->fetchAll($sql, [$limit, $offset]);
    }
    
    /**
     * Search users with pagination
     */
    public function searchPaginated($query, $limit = 10, $offset = 0) {
        $searchTerm = '%' . $query . '%';
        $sql = "SELECT * FROM users 
                WHERE username LIKE ? OR email LIKE ?
                ORDER BY created_at DESC 
                LIMIT ? OFFSET ?";
        return $this->db->fetchAll($sql, [$searchTerm, $searchTerm, $limit, $offset]);
    }
    
    /**
     * Count total users
     */
    public function countTotal() {
        $sql = "SELECT COUNT(*) as total FROM users";
        $result = $this->db->fetchOne($sql);
        return $result ? (int)$result['total'] : 0;
    }
    
    /**
     * Count search results
     */
    public function countSearch($query) {
        $searchTerm = '%' . $query . '%';
        $sql = "SELECT COUNT(*) as total FROM users 
                WHERE username LIKE ? OR email LIKE ?";
        $result = $this->db->fetchOne($sql, [$searchTerm, $searchTerm]);
        return $result ? (int)$result['total'] : 0;
    }
}
