<?php
require_once APP_PATH . '/Core/BaseModel.php';

class User extends BaseModel {
    protected string $table = 'users';

    public function findByEmail(string $email): ?array {
        return $this->findBy('email', $email);
    }

    public function findByVerifyToken(string $token): ?array {
        return $this->findBy('verify_token', $token);
    }

    public function findByResetToken(string $token): ?array {
        return $this->fetchOne(
            "SELECT * FROM users WHERE reset_token = ? AND reset_expires > NOW() LIMIT 1",
            [$token]
        );
    }

    public function createUser(array $data): int {
        $data['uuid']          = generateUUID();
        $data['password_hash'] = password_hash($data['password'], PASSWORD_BCRYPT, ['cost' => 12]);
        $data['verify_token']  = bin2hex(random_bytes(32));
        $data['status']        = 'pending';
        unset($data['password'], $data['password_confirm']);
        return $this->create($data);
    }

    public function verifyEmail(string $token): bool {
        return $this->execute(
            "UPDATE users SET email_verified = 1, status = 'active', verify_token = NULL WHERE verify_token = ?",
            [$token]
        );
    }

    public function updatePassword(int $id, string $password): bool {
        $hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
        return $this->execute(
            "UPDATE users SET password_hash = ?, reset_token = NULL, reset_expires = NULL WHERE id = ?",
            [$hash, $id]
        );
    }

    public function setResetToken(int $id): string {
        $token = bin2hex(random_bytes(32));
        $this->execute(
            "UPDATE users SET reset_token = ?, reset_expires = DATE_ADD(NOW(), INTERVAL 1 HOUR) WHERE id = ?",
            [$token, $id]
        );
        return $token;
    }

    public function recordLogin(int $id): void {
        $this->execute(
            "UPDATE users SET last_login = NOW(), login_attempts = 0, locked_until = NULL WHERE id = ?",
            [$id]
        );
    }

    public function incrementLoginAttempts(int $id): void {
        $this->execute(
            "UPDATE users SET login_attempts = login_attempts + 1 WHERE id = ?",
            [$id]
        );
        $user = $this->find($id);
        if ($user && $user['login_attempts'] >= 5) {
            $this->execute(
                "UPDATE users SET locked_until = DATE_ADD(NOW(), INTERVAL 15 MINUTE) WHERE id = ?",
                [$id]
            );
        }
    }

    public function isLocked(array $user): bool {
        if (empty($user['locked_until'])) return false;
        return strtotime($user['locked_until']) > time();
    }

    public function searchUsers(string $q, ?string $role = null, int $page = 1): array {
        $where  = "(first_name LIKE ? OR last_name LIKE ? OR email LIKE ?)";
        $params = ["%{$q}%", "%{$q}%", "%{$q}%"];
        if ($role) {
            $where  .= " AND role = ?";
            $params[] = $role;
        }
        return $this->paginate($page, ITEMS_PER_PAGE, $where, $params, 'created_at DESC');
    }

    public function countByRole(): array {
        $rows = $this->fetchAll("SELECT role, COUNT(*) AS cnt FROM users GROUP BY role");
        $result = [];
        foreach ($rows as $row) {
            $result[$row['role']] = (int) $row['cnt'];
        }
        return $result;
    }

    public function recentUsers(int $limit = 10): array {
        return $this->fetchAll(
            "SELECT * FROM users ORDER BY created_at DESC LIMIT ?",
            [$limit]
        );
    }
}
