<?php
/**
 * ============================================================
 * INPUT VALIDATOR
 * ============================================================
 * Simple validation class for form inputs
 */

class Validator {
    private array $errors = [];
    private array $data = [];
    
    /**
     * Create validator with data
     * @param array $data
     */
    public function __construct(array $data) {
        $this->data = $data;
    }
    
    /**
     * Static factory method
     * @param array $data
     * @return self
     */
    public static function make(array $data): self {
        return new self($data);
    }
    
    /**
     * Validate required field
     * @param string $field
     * @param string $label
     * @return self
     */
    public function required(string $field, string $label = ''): self {
        $label = $label ?: $field;
        $value = $this->data[$field] ?? '';
        
        if (is_string($value) && trim($value) === '') {
            $this->errors[$field] = "{$label} আবশ্যক";
        } elseif (empty($value)) {
            $this->errors[$field] = "{$label} আবশ্যক";
        }
        
        return $this;
    }
    
    /**
     * Validate email format
     * @param string $field
     * @param string $label
     * @return self
     */
    public function email(string $field, string $label = 'ইমেইল'): self {
        $value = $this->data[$field] ?? '';
        
        if (!empty($value) && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
            $this->errors[$field] = "সঠিক {$label} দিন";
        }
        
        return $this;
    }
    
    /**
     * Validate minimum length
     * @param string $field
     * @param int $min
     * @param string $label
     * @return self
     */
    public function minLength(string $field, int $min, string $label = ''): self {
        $label = $label ?: $field;
        $value = $this->data[$field] ?? '';
        
        if (!empty($value) && mb_strlen($value) < $min) {
            $this->errors[$field] = "{$label} কমপক্ষে {$min} অক্ষরের হতে হবে";
        }
        
        return $this;
    }
    
    /**
     * Validate maximum length
     * @param string $field
     * @param int $max
     * @param string $label
     * @return self
     */
    public function maxLength(string $field, int $max, string $label = ''): self {
        $label = $label ?: $field;
        $value = $this->data[$field] ?? '';
        
        if (!empty($value) && mb_strlen($value) > $max) {
            $this->errors[$field] = "{$label} সর্বোচ্চ {$max} অক্ষরের হতে পারবে";
        }
        
        return $this;
    }
    
    /**
     * Validate numeric value
     * @param string $field
     * @param string $label
     * @return self
     */
    public function numeric(string $field, string $label = ''): self {
        $label = $label ?: $field;
        $value = $this->data[$field] ?? '';
        
        if (!empty($value) && !is_numeric($value)) {
            $this->errors[$field] = "{$label} সংখ্যা হতে হবে";
        }
        
        return $this;
    }
    
    /**
     * Validate integer value
     * @param string $field
     * @param string $label
     * @return self
     */
    public function integer(string $field, string $label = ''): self {
        $label = $label ?: $field;
        $value = $this->data[$field] ?? '';
        
        if (!empty($value) && !filter_var($value, FILTER_VALIDATE_INT)) {
            $this->errors[$field] = "{$label} পূর্ণসংখ্যা হতে হবে";
        }
        
        return $this;
    }
    
    /**
     * Validate minimum value
     * @param string $field
     * @param float $min
     * @param string $label
     * @return self
     */
    public function min(string $field, float $min, string $label = ''): self {
        $label = $label ?: $field;
        $value = $this->data[$field] ?? 0;
        
        if (is_numeric($value) && (float)$value < $min) {
            $this->errors[$field] = "{$label} কমপক্ষে {$min} হতে হবে";
        }
        
        return $this;
    }
    
    /**
     * Validate maximum value
     * @param string $field
     * @param float $max
     * @param string $label
     * @return self
     */
    public function max(string $field, float $max, string $label = ''): self {
        $label = $label ?: $field;
        $value = $this->data[$field] ?? 0;
        
        if (is_numeric($value) && (float)$value > $max) {
            $this->errors[$field] = "{$label} সর্বোচ্চ {$max} হতে পারবে";
        }
        
        return $this;
    }
    
    /**
     * Validate Bangladesh phone number
     * @param string $field
     * @param string $label
     * @return self
     */
    public function phone(string $field, string $label = 'মোবাইল নম্বর'): self {
        $value = $this->data[$field] ?? '';
        
        if (!empty($value)) {
            // Remove spaces and dashes
            $phone = preg_replace('/[\s\-]/', '', $value);
            
            // Bangladesh phone: 01XXXXXXXXX (11 digits) or +8801XXXXXXXXX
            $pattern = '/^(\+?880)?1[3-9]\d{8}$/';
            
            if (!preg_match($pattern, $phone)) {
                $this->errors[$field] = "সঠিক {$label} দিন (01XXXXXXXXX)";
            }
        }
        
        return $this;
    }
    
    /**
     * Validate value is in array
     * @param string $field
     * @param array $allowed
     * @param string $label
     * @return self
     */
    public function in(string $field, array $allowed, string $label = ''): self {
        $label = $label ?: $field;
        $value = $this->data[$field] ?? '';
        
        if (!empty($value) && !in_array($value, $allowed, true)) {
            $this->errors[$field] = "{$label} অবৈধ";
        }
        
        return $this;
    }
    
    /**
     * Validate password confirmation matches
     * @param string $field
     * @param string $confirmField
     * @return self
     */
    public function confirmed(string $field, string $confirmField = ''): self {
        $confirmField = $confirmField ?: $field . '_confirmation';
        $value = $this->data[$field] ?? '';
        $confirm = $this->data[$confirmField] ?? '';
        
        if (!empty($value) && $value !== $confirm) {
            $this->errors[$confirmField] = 'পাসওয়ার্ড মিলছে না';
        }
        
        return $this;
    }
    
    /**
     * Validate file upload
     * @param string $field
     * @param array $allowedTypes
     * @param int $maxSize in bytes
     * @param string $label
     * @return self
     */
    public function file(string $field, array $allowedTypes = [], int $maxSize = 0, string $label = 'ফাইল'): self {
        if (!isset($_FILES[$field]) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) {
            return $this;
        }
        
        $file = $_FILES[$field];
        
        if ($file['error'] !== UPLOAD_ERR_OK) {
            $this->errors[$field] = "{$label} আপলোড ব্যর্থ হয়েছে";
            return $this;
        }
        
        if (!empty($allowedTypes)) {
            $finfo = finfo_open(FILEINFO_MIME_TYPE);
            $mimeType = finfo_file($finfo, $file['tmp_name']);
            finfo_close($finfo);
            
            if (!in_array($mimeType, $allowedTypes)) {
                $this->errors[$field] = "{$label} ফরম্যাট সমর্থিত নয়";
            }
        }
        
        if ($maxSize > 0 && $file['size'] > $maxSize) {
            $maxMB = round($maxSize / (1024 * 1024), 1);
            $this->errors[$field] = "{$label} সর্বোচ্চ {$maxMB}MB হতে পারবে";
        }
        
        return $this;
    }
    
    /**
     * Add custom error
     * @param string $field
     * @param string $message
     * @return self
     */
    public function addError(string $field, string $message): self {
        $this->errors[$field] = $message;
        return $this;
    }
    
    /**
     * Check if validation passed
     * @return bool
     */
    public function passes(): bool {
        return empty($this->errors);
    }
    
    /**
     * Check if validation failed
     * @return bool
     */
    public function fails(): bool {
        return !empty($this->errors);
    }
    
    /**
     * Get all errors
     * @return array
     */
    public function errors(): array {
        return $this->errors;
    }
    
    /**
     * Get first error message
     * @return string|null
     */
    public function firstError(): ?string {
        return !empty($this->errors) ? reset($this->errors) : null;
    }
    
    /**
     * Get validated data (only fields that were validated)
     * @return array
     */
    public function validated(): array {
        return $this->data;
    }
}
