<?php

namespace App\Core;

/**
 * Validator - فئة التحقق من المدخلات
 */
class Validator
{
    private array $data;
    private array $rules;
    private array $errors = [];
    private array $customMessages = [];

    public function __construct(array $data, array $rules, array $customMessages = [])
    {
        $this->data = $data;
        $this->rules = $rules;
        $this->customMessages = $customMessages;
    }

    /**
     * التحقق من جميع القواعد
     */
    public function validate(): bool
    {
        $this->errors = [];

        foreach ($this->rules as $field => $rules) {
            $rulesArray = is_string($rules) ? explode('|', $rules) : $rules;
            
            foreach ($rulesArray as $rule) {
                $this->validateField($field, $rule);
            }
        }

        return empty($this->errors);
    }

    /**
     * التحقق من حقل واحد
     */
    private function validateField(string $field, string $rule): void
    {
        $value = $this->data[$field] ?? null;
        $ruleParts = explode(':', $rule, 2);
        $ruleName = $ruleParts[0];
        $ruleValue = $ruleParts[1] ?? null;

        switch ($ruleName) {
            case 'required':
                if ($value === null || $value === '' || (is_array($value) && empty($value))) {
                    $this->addError($field, 'required', 'هذا الحقل مطلوب');
                }
                break;

            case 'email':
                if ($value !== null && $value !== '' && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
                    $this->addError($field, 'email', 'البريد الإلكتروني غير صحيح');
                }
                break;

            case 'phone':
                if ($value !== null && $value !== '') {
                    $phone = preg_replace('/\D/', '', $value);
                    if (strlen($phone) < 7) {
                        $this->addError($field, 'phone', 'رقم الهاتف غير صحيح');
                    }
                }
                break;

            case 'numeric':
                if ($value !== null && $value !== '' && !is_numeric($value)) {
                    $this->addError($field, 'numeric', 'يجب أن يكون رقماً');
                }
                break;

            case 'integer':
                if ($value !== null && $value !== '' && !is_numeric($value) || (int)$value != $value) {
                    $this->addError($field, 'integer', 'يجب أن يكون رقماً صحيحاً');
                }
                break;

            case 'min':
                if ($value !== null && $value !== '') {
                    $min = (int)$ruleValue;
                    if (is_numeric($value) && (float)$value < $min) {
                        $this->addError($field, 'min', "القيمة يجب أن تكون على الأقل {$min}");
                    } elseif (is_string($value) && mb_strlen($value) < $min) {
                        $this->addError($field, 'min', "يجب أن يكون على الأقل {$min} أحرف");
                    }
                }
                break;

            case 'max':
                if ($value !== null && $value !== '') {
                    $max = (int)$ruleValue;
                    if (is_numeric($value) && (float)$value > $max) {
                        $this->addError($field, 'max', "القيمة يجب أن تكون على الأكثر {$max}");
                    } elseif (is_string($value) && mb_strlen($value) > $max) {
                        $this->addError($field, 'max', "يجب أن يكون على الأكثر {$max} أحرف");
                    }
                }
                break;

            case 'date':
                if ($value !== null && $value !== '') {
                    $date = date_create($value);
                    if (!$date) {
                        $this->addError($field, 'date', 'التاريخ غير صحيح');
                    }
                }
                break;

            case 'date_format':
                if ($value !== null && $value !== '') {
                    $format = $ruleValue ?? 'Y-m-d';
                    $date = \DateTime::createFromFormat($format, $value);
                    if (!$date || $date->format($format) !== $value) {
                        $this->addError($field, 'date_format', "التاريخ يجب أن يكون بصيغة {$format}");
                    }
                }
                break;

            case 'in':
                if ($value !== null && $value !== '') {
                    $allowed = explode(',', $ruleValue ?? '');
                    if (!in_array($value, $allowed, true)) {
                        $this->addError($field, 'in', 'القيمة غير مسموحة');
                    }
                }
                break;

            case 'regex':
                if ($value !== null && $value !== '') {
                    $pattern = $ruleValue ?? '';
                    if (!preg_match($pattern, $value)) {
                        $this->addError($field, 'regex', 'الصيغة غير صحيحة');
                    }
                }
                break;

            case 'url':
                if ($value !== null && $value !== '' && !filter_var($value, FILTER_VALIDATE_URL)) {
                    $this->addError($field, 'url', 'الرابط غير صحيح');
                }
                break;

            case 'same':
                if ($value !== null && $value !== '') {
                    $otherField = $ruleValue ?? '';
                    $otherValue = $this->data[$otherField] ?? null;
                    if ($value !== $otherValue) {
                        $this->addError($field, 'same', 'القيمتان غير متطابقتين');
                    }
                }
                break;
        }
    }

    /**
     * إضافة خطأ
     */
    private function addError(string $field, string $rule, string $defaultMessage): void
    {
        $key = "{$field}.{$rule}";
        $message = $this->customMessages[$key] ?? $defaultMessage;
        
        if (!isset($this->errors[$field])) {
            $this->errors[$field] = [];
        }
        
        $this->errors[$field][] = $message;
    }

    /**
     * التحقق من نجاح التحقق
     */
    public function passes(): bool
    {
        return $this->validate();
    }

    /**
     * التحقق من فشل التحقق
     */
    public function fails(): bool
    {
        return !$this->validate();
    }

    /**
     * جلب الأخطاء
     */
    public function errors(): array
    {
        return $this->errors;
    }

    /**
     * جلب أول خطأ لحقل معين
     */
    public function first(string $field): ?string
    {
        return $this->errors[$field][0] ?? null;
    }

    /**
     * جلب جميع أخطاء حقل معين
     */
    public function get(string $field): array
    {
        return $this->errors[$field] ?? [];
    }

    /**
     * التحقق السريع (static method)
     */
    public static function make(array $data, array $rules, array $customMessages = []): self
    {
        $validator = new self($data, $rules, $customMessages);
        $validator->validate();
        return $validator;
    }
}
