<?php

namespace lib\Core\Http;

//사용법
// $validator = new \lib\Http\Validator();

// $validator->setData([
//   'username' => 'admin123',
//   'email' => 'admin@example.com',
//   'password' => '1234'
// ])->setRules([
//   'username' => 'required|alpha_numeric|min[4]|max[20]',
//   'email' => 'required|email',
//   'password' => 'required|min[6]'
// ]);

// if (!$validator->run()) {
//   print_r($validator->errors());
// }

class Validator extends Http
{
  protected array $data = [];
  protected array $rules = [];
  protected array $errors = [];
  protected array $customMessages = [];

  protected array $availableRules = [
    'required',
    'min',
    'max',
    'email',
    'numeric',
    'alpha',
    'alpha_numeric'
  ];

  public function __construct()
  {
    parent::__construct();
  }

  public function setData(array $data): self
  {
    $this->data = $data;
    return $this;
  }

  public function setRules(array $rules): self
  {
    $this->rules = $rules;
    return $this;
  }

  public function setMessages(array $messages): self
  {
    $this->customMessages = $messages;
    return $this;
  }

  public function run(): bool
  {
    $this->errors = [];

    foreach ($this->rules as $field => $ruleStr) {
      $rules = explode('|', $ruleStr);
      $value = $this->data[$field] ?? null;

      foreach ($rules as $rule) {
        $param = null;
        if (strpos($rule, '[') !== false) {
          preg_match('/(\w+)\[(.*?)\]/', $rule, $matches);
          $rule = $matches[1];
          $param = $matches[2];
        }

        $method = "validate_$rule";
        if (method_exists($this, $method)) {
          $result = $this->$method($value, $param);
          if (!$result) {
            $this->addError($field, $rule, $param);
          }
        }
      }
    }

    return empty($this->errors);
  }

  public function errors(): array
  {
    return $this->errors;
  }

  protected function addError(string $field, string $rule, $param = null): void
  {
    $message = $this->customMessages["$field.$rule"] ?? $this->defaultMessage($field, $rule, $param);
    $this->errors[$field][] = $message;
  }

  protected function defaultMessage(string $field, string $rule, $param): string
  {
    return match ($rule) {
      'required' => "$field is required.",
      'min' => "$field must be at least $param characters.",
      'max' => "$field must be at most $param characters.",
      'email' => "$field must be a valid email address.",
      'numeric' => "$field must be a number.",
      'alpha' => "$field must contain only letters.",
      'alpha_numeric' => "$field must contain only letters and numbers.",
      default => "$field is invalid.",
    };
  }

  // --- 기본 유효성 검사 메서드 ---
  protected function validate_required($value): bool
  {
    return !empty($value) || $value === '0';
  }

  protected function validate_min($value, $param): bool
  {
    return strlen($value) >= (int)$param;
  }

  protected function validate_max($value, $param): bool
  {
    return strlen($value) <= (int)$param;
  }

  protected function validate_email($value): bool
  {
    return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
  }

  protected function validate_numeric($value): bool
  {
    return is_numeric($value);
  }

  protected function validate_alpha($value): bool
  {
    return ctype_alpha($value);
  }

  protected function validate_alpha_numeric($value): bool
  {
    return ctype_alnum($value);
  }

  // 사용자 정의 규칙도 등록할 수 있도록 향후 확장 가능
}
