<?php

namespace App\DTOs;

use ReflectionClass;
use ReflectionNamedType;

abstract class CommonDTO
{
  protected function __construct(array $datas = [])
  {
    if (empty($datas)) return;

    $reflection = new ReflectionClass($this);

    foreach ($datas as $key => $value) {
      if (!$reflection->hasProperty($key)) continue;

      $property = $reflection->getProperty($key);
      $type = $property->getType();
      $assignValue = $value;

      if ($value === '') {
        $assignValue = null;
      } elseif ($type instanceof ReflectionNamedType) {
        $typeName = $type->getName();

        // [추가] 타입이 array인 경우 처리
        if ($typeName === 'array' && is_string($value)) {
          $assignValue = explode(DEFAULTS["DELIMITER_ROLE"], $value);
        } elseif ($typeName === 'int' && is_numeric($value)) {
          $assignValue = (int) $value;
        }
        // ... float 등 기존 로직 ...
      }

      $this->{$key} = $assignValue;
    }
  }

  // [중요] final 해제 또는 로직 변경
  public function toArray(): array
  {
    // get_object_vars는 protected를 가져오지 못하므로 
    // Reflection을 사용하여 모든 프로퍼티를 가져오되, 
    // 값을 가져올 때는 $this->{$name}을 통해 Getter나 매직메서드가 작동하게 합니다.
    $reflection = new ReflectionClass($this);
    $properties = $reflection->getProperties();
    $result = [];

    foreach ($properties as $property) {
      $name = $property->getName();
      // $this->$name 처리를 통해 자식의 __get()이 호출되도록 유도
      $result[$name] = $this->{$name};
    }

    return $result;
  }
}
