<?php
/**
 * ZLO Platform - User Model
 */

declare(strict_types=1);

require_once __DIR__ . '/../core/Model.php';

class User extends Model
{
    protected string $table = 'users';
    protected string $primaryKey = 'id';
    
    protected array $fillable = [
        'name',
        'email',
        'password',
        'role_id',
        'avatar',
        'phone',
        'status'
    ];
    
    protected array $hidden = [
        'password',
        'remember_token'
    ];
    
    protected array $casts = [
        'id' => 'int',
        'role_id' => 'int',
        'status' => 'string',
        'last_login' => 'datetime',
        'created_at' => 'datetime',
        'updated_at' => 'datetime'
    ];
    
    /**
     * Find user by email
     */
    public function findByEmail(string $email): ?array
    {
        return $this->findBy('email', $email);
    }
    
    /**
     * Authenticate user
     */
    public function authenticate(string $email, string $password): ?array
    {
        $user = $this->findByEmail($email);
        
        if (!$user) {
            return null;
        }
        
        // Get password hash (need to bypass hidden fields)
        $sql = "SELECT password FROM {$this->table} WHERE id = ?";
        $result = $this->db->fetchOne($sql, [$user['id']]);
        
        if (!$result || !$this->security->verifyPassword($password, $result['password'])) {
            return null;
        }
        
        // Update last login
        $this->update($user['id'], [
            'last_login' => date('Y-m-d H:i:s')
        ]);
        
        // Load role and permissions
        $user['role'] = $this->getRole($user['role_id']);
        $user['permissions'] = $this->getPermissions($user['role_id']);
        
        return $user;
    }
    
    /**
     * Create user with hashed password
     */
    public function create(array $data): int
    {
        if (!empty($data['password'])) {
            $data['password'] = $this->security->hashPassword($data['password']);
        }
        
        return parent::create($data);
    }
    
    /**
     * Update user with optional password change
     */
    public function update(int $id, array $data): bool
    {
        if (!empty($data['password'])) {
            $data['password'] = $this->security->hashPassword($data['password']);
        }
        
        return parent::update($id, $data);
    }
    
    /**
     * Get user role
     */
    public function getRole(int $roleId): ?array
    {
        $sql = "SELECT * FROM roles WHERE id = ?";
        return $this->db->fetchOne($sql, [$roleId]);
    }
    
    /**
     * Get role permissions
     */
    public function getPermissions(int $roleId): array
    {
        $sql = "SELECT p.name, p.module 
                FROM permissions p 
                INNER JOIN role_permissions rp ON p.id = rp.permission_id 
                WHERE rp.role_id = ?";
        
        return $this->db->fetchAll($sql, [$roleId]);
    }
    
    /**
     * Check if user has permission
     */
    public function hasPermission(int $userId, string $permission): bool
    {
        $user = $this->find($userId);
        
        if (!$user) {
            return false;
        }
        
        $permissions = $this->getPermissions($user['role_id']);
        
        foreach ($permissions as $p) {
            if ($p['name'] === $permission) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Get all users with roles
     */
    public function getAllWithRoles(array $options = []): array
    {
        $sql = "SELECT u.*, r.name as role_name, r.description as role_description 
                FROM {$this->table} u 
                LEFT JOIN roles r ON u.role_id = r.id";
        
        $params = [];
        
        if (!empty($options['status'])) {
            $sql .= " WHERE u.status = ?";
            $params[] = $options['status'];
        }
        
        $sql .= " ORDER BY u.created_at DESC";
        
        if (!empty($options['limit'])) {
            $sql .= " LIMIT ?";
            $params[] = (int) $options['limit'];
        }
        
        return $this->db->fetchAll($sql, $params);
    }
    
    /**
     * Generate remember token
     */
    public function generateRememberToken(int $userId): string
    {
        $token = $this->security->generateToken(64);
        
        $this->db->update(
            $this->table,
            ['remember_token' => $token],
            "id = ?",
            [$userId]
        );
        
        return $token;
    }
    
    /**
     * Find by remember token
     */
    public function findByRememberToken(string $token): ?array
    {
        return $this->findBy('remember_token', $token);
    }
    
    /**
     * Get dashboard stats
     */
    public function getStats(): array
    {
        return [
            'total' => $this->count(),
            'active' => $this->count(['status' => 'active']),
            'suspended' => $this->count(['status' => 'suspended']),
            'pending' => $this->count(['status' => 'pending'])
        ];
    }
}
