<?php
/**
 * Input Validator
 */
class Validator {
    private array $errors = [];
    private array $data;
    
    public function __construct(array $data) {
        $this->data = $data;
    }
    
    public function required(string $field, ?string $label = null): self {
        $label = $label ?? ucfirst(str_replace('_', ' ', $field));
        if (empty($this->data[$field]) && $this->data[$field] !== '0') {
            $this->errors[$field] = "$label is required.";
        }
        return $this;
    }
    
    public function email(string $field, ?string $label = null): self {
        $label = $label ?? ucfirst(str_replace('_', ' ', $field));
        if (!empty($this->data[$field]) && !filter_var($this->data[$field], FILTER_VALIDATE_EMAIL)) {
            $this->errors[$field] = "$label must be a valid email address.";
        }
        return $this;
    }
    
    public function min(string $field, int $length, ?string $label = null): self {
        $label = $label ?? ucfirst(str_replace('_', ' ', $field));
        if (!empty($this->data[$field]) && strlen($this->data[$field]) < $length) {
            $this->errors[$field] = "$label must be at least $length characters.";
        }
        return $this;
    }
    
    public function max(string $field, int $length, ?string $label = null): self {
        $label = $label ?? ucfirst(str_replace('_', ' ', $field));
        if (!empty($this->data[$field]) && strlen($this->data[$field]) > $length) {
            $this->errors[$field] = "$label must not exceed $length characters.";
        }
        return $this;
    }
    
    public function numeric(string $field, ?string $label = null): self {
        $label = $label ?? ucfirst(str_replace('_', ' ', $field));
        if (!empty($this->data[$field]) && !is_numeric($this->data[$field])) {
            $this->errors[$field] = "$label must be a number.";
        }
        return $this;
    }
    
    public function date(string $field, ?string $label = null): self {
        $label = $label ?? ucfirst(str_replace('_', ' ', $field));
        if (!empty($this->data[$field]) && strtotime($this->data[$field]) === false) {
            $this->errors[$field] = "$label must be a valid date.";
        }
        return $this;
    }
    
    public function unique(string $field, string $table, ?string $column = null, ?int $exceptId = null, ?string $label = null): self {
        $label = $label ?? ucfirst(str_replace('_', ' ', $field));
        $column = $column ?? $field;
        
        if (!empty($this->data[$field])) {
            $db = Database::getInstance();
            $sql = "SELECT id FROM `$table` WHERE `$column` = ? AND deleted_at IS NULL";
            $params = [$this->data[$field]];
            
            if ($exceptId) {
                $sql .= " AND id != ?";
                $params[] = $exceptId;
            }
            
            if ($db->fetch($sql, $params)) {
                $this->errors[$field] = "$label already exists.";
            }
        }
        return $this;
    }
    
    public function matches(string $field, string $matchField, ?string $label = null): self {
        $label = $label ?? ucfirst(str_replace('_', ' ', $field));
        if (($this->data[$field] ?? '') !== ($this->data[$matchField] ?? '')) {
            $this->errors[$field] = "$label does not match.";
        }
        return $this;
    }
    
    public function passes(): bool {
        return empty($this->errors);
    }
    
    public function fails(): bool {
        return !$this->passes();
    }
    
    public function errors(): array {
        return $this->errors;
    }
    
    public function firstError(): ?string {
        return reset($this->errors) ?: null;
    }
}
