<?php

namespace Openguru\OpenCartFramework\CriteriaBuilder;

use Openguru\OpenCartFramework\CriteriaBuilder\Rules\BaseRule;
use ReflectionClass;
use ReflectionProperty;

class RuleSerializer
{
    public function toArray(BaseRule $rule): array
    {
        return $this->extractProperties($rule);
    }

    public function extractProperties(object $object): array
    {
        $reflection = new ReflectionClass($object);
        $properties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC);

        $data = [];

        foreach ($properties as $property) {
            $propertyName = $property->getName();
            $propertyValue = $property->getValue($object);

            if (is_object($propertyValue)) {
                $data[$propertyName] = $this->extractProperties($propertyValue);
            } elseif (is_array($propertyValue)) {
                $data[$propertyName] = $this->extractArray($propertyValue);
            } else {
                $data[$propertyName] = $propertyValue;
            }
        }

        if ($reflection->hasMethod('metaAttributes')) {
            $data['__meta'] = $reflection->getMethod('metaAttributes')->invoke($object);
        }

        return $data;
    }

    private function extractArray(array $array): array
    {
        $data = [];
        foreach ($array as $key => $value) {
            if (is_object($value)) {
                $data[$key] = $this->extractProperties($value);
            } elseif (is_array($value)) {
                $data[$key] = $this->extractArray($value);
            } else {
                $data[$key] = $value;
            }
        }

        return $data;
    }
}
