<?php

class Validator
{

    private $errors = [];
    private $data = [];

    public function __construct($data = [])
    {
        $this->data = $data;
        $this->errors = [];
    }

    /**
     * Validate required fields
     */
    public function required($fields)
    {
        if (!is_array($fields)) {
            $fields = [$fields];
        }

        foreach ($fields as $field) {
            if (!isset($this->data[$field]) || empty(trim($this->data[$field]))) {
                $this->errors[$field][] = "Field '{$field}' is required";
            }
        }

        return $this;
    }

    /**
     * Validate email format
     */
    public function email($field)
    {
        if (isset($this->data[$field]) && !empty($this->data[$field])) {
            if (!filter_var($this->data[$field], FILTER_VALIDATE_EMAIL)) {
                $this->errors[$field][] = "Field '{$field}' must be a valid email address";
            }
        }

        return $this;
    }

    /**
     * Validate phone number
     */
    public function phone($field)
    {
        if (isset($this->data[$field]) && !empty($this->data[$field])) {
            if (!preg_match('/^[0-9]{10,15}$/', $this->data[$field])) {
                $this->errors[$field][] = "Field '{$field}' must be a valid phone number (10-15 digits)";
            }
        }

        return $this;
    }

    /**
     * Validate minimum length
     */
    public function minLength($field, $length)
    {
        if (isset($this->data[$field]) && !empty($this->data[$field])) {
            if (strlen($this->data[$field]) < $length) {
                $this->errors[$field][] = "Field '{$field}' must be at least {$length} characters long";
            }
        }

        return $this;
    }

    /**
     * Validate maximum length
     */
    public function maxLength($field, $length)
    {
        if (isset($this->data[$field]) && !empty($this->data[$field])) {
            if (strlen($this->data[$field]) > $length) {
                $this->errors[$field][] = "Field '{$field}' must not exceed {$length} characters";
            }
        }

        return $this;
    }

    /**
     * Validate numeric value
     */
    public function numeric($field)
    {
        if (isset($this->data[$field]) && !empty($this->data[$field])) {
            if (!is_numeric($this->data[$field])) {
                $this->errors[$field][] = "Field '{$field}' must be numeric";
            }
        }

        return $this;
    }

    /**
     * Validate integer value
     */
    public function integer($field)
    {
        if (isset($this->data[$field]) && !empty($this->data[$field])) {
            if (!filter_var($this->data[$field], FILTER_VALIDATE_INT)) {
                $this->errors[$field][] = "Field '{$field}' must be an integer";
            }
        }

        return $this;
    }

    /**
     * Validate URL format
     */
    public function url($field)
    {
        if (isset($this->data[$field]) && !empty($this->data[$field])) {
            if (!filter_var($this->data[$field], FILTER_VALIDATE_URL)) {
                $this->errors[$field][] = "Field '{$field}' must be a valid URL";
            }
        }

        return $this;
    }

    /**
     * Validate date format
     */
    public function date($field, $format = 'Y-m-d')
    {
        if (isset($this->data[$field]) && !empty($this->data[$field])) {
            $date = DateTime::createFromFormat($format, $this->data[$field]);
            if (!$date || $date->format($format) !== $this->data[$field]) {
                $this->errors[$field][] = "Field '{$field}' must be a valid date in format {$format}";
            }
        }

        return $this;
    }

    /**
     * Validate value is in array
     */
    public function in($field, $values)
    {
        if (isset($this->data[$field]) && !empty($this->data[$field])) {
            if (!in_array($this->data[$field], $values)) {
                $allowedValues = implode(', ', $values);
                $this->errors[$field][] = "Field '{$field}' must be one of: {$allowedValues}";
            }
        }

        return $this;
    }

    /**
     * Validate regex pattern
     */
    public function regex($field, $pattern)
    {
        if (isset($this->data[$field]) && !empty($this->data[$field])) {
            if (!preg_match($pattern, $this->data[$field])) {
                $this->errors[$field][] = "Field '{$field}' format is invalid";
            }
        }

        return $this;
    }

    /**
     * Custom validation rule
     */
    public function custom($field, $callback, $message = null)
    {
        if (isset($this->data[$field])) {
            $result = call_user_func($callback, $this->data[$field]);
            if (!$result) {
                $message = $message ?: "Field '{$field}' is invalid";
                $this->errors[$field][] = $message;
            }
        }

        return $this;
    }

    /**
     * Validate file upload
     */
    public function file($field, $allowedTypes = null, $maxSize = null)
    {
        if (isset($_FILES[$field])) {
            $file = $_FILES[$field];

            // Check upload error
            if ($file['error'] !== UPLOAD_ERR_OK) {
                $this->errors[$field][] = "File upload failed";
                return $this;
            }

            // Check file size
            if ($maxSize && $file['size'] > $maxSize) {
                $maxSizeMB = $maxSize / (1024 * 1024);
                $this->errors[$field][] = "File size must not exceed {$maxSizeMB}MB";
            }

            // Check file type
            if ($allowedTypes) {
                $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
                if (!in_array($extension, $allowedTypes)) {
                    $allowedTypesStr = implode(', ', $allowedTypes);
                    $this->errors[$field][] = "File type must be one of: {$allowedTypesStr}";
                }
            }
        }

        return $this;
    }

    /**
     * Check if validation passed
     */
    public function passes()
    {
        return empty($this->errors);
    }

    /**
     * Check if validation failed
     */
    public function fails()
    {
        return !empty($this->errors);
    }

    /**
     * Get all errors
     */
    public function getErrors()
    {
        return $this->errors;
    }

    /**
     * Get errors for specific field
     */
    public function getFieldErrors($field)
    {
        return $this->errors[$field] ?? [];
    }

    /**
     * Get first error message
     */
    public function getFirstError()
    {
        if (empty($this->errors)) {
            return null;
        }

        $firstField = array_key_first($this->errors);
        return $this->errors[$firstField][0] ?? null;
    }

    /**
     * Get all error messages as flat array
     */
    public function getAllMessages()
    {
        $messages = [];
        foreach ($this->errors as $fieldErrors) {
            $messages = array_merge($messages, $fieldErrors);
        }
        return $messages;
    }

    /**
     * Add custom error
     */
    public function addError($field, $message)
    {
        $this->errors[$field][] = $message;
        return $this;
    }

    /**
     * Clear all errors
     */
    public function clearErrors()
    {
        $this->errors = [];
        return $this;
    }

    /**
     * Set validation data
     */
    public function setData($data)
    {
        $this->data = $data;
        $this->errors = [];
        return $this;
    }

    /**
     * Static method to create validator instance
     */
    public static function make($data)
    {
        return new self($data);
    }
}
