<?php
class FileUpload
{
    private ?array $file;
    private array $allowedTypes = ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xls', 'xlsx'];
    private int $maxSize = 10485760; // 10MB
    private string $destination = 'uploads/';
    private array $errors = [];

    public function __construct(?array $file)
    {
        $this->file = $file;
    }

    public function setAllowedTypes(array $types): self
    {
        $this->allowedTypes = $types;
        return $this;
    }

    public function setMaxSize(int $bytes): self
    {
        $this->maxSize = $bytes;
        return $this;
    }

    public function setDestination(string $path): self
    {
        $this->destination = $path;
        return $this;
    }

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

        if (!$this->file || $this->file['error'] === UPLOAD_ERR_NO_FILE) {
            $this->errors[] = 'No file uploaded';
            return false;
        }

        if ($this->file['error'] !== UPLOAD_ERR_OK) {
            $this->errors[] = 'Upload error: ' . $this->file['error'];
            return false;
        }

        $ext = strtolower(pathinfo($this->file['name'], PATHINFO_EXTENSION));
        if (!in_array($ext, $this->allowedTypes)) {
            $this->errors[] = 'File type not allowed. Allowed: ' . implode(', ', $this->allowedTypes);
            return false;
        }

        if ($this->file['size'] > $this->maxSize) {
            $this->errors[] = 'File too large. Max: ' . round($this->maxSize / 1048576, 1) . 'MB';
            return false;
        }

        return true;
    }

    public function save(?string $customName = null): ?string
    {
        if (!empty($this->errors)) {
            return null;
        }

        $fullPath = PUBLIC_PATH . '/' . rtrim($this->destination, '/') . '/';
        if (!is_dir($fullPath)) {
            @mkdir($fullPath, 0755, true);
        }

        $ext = strtolower(pathinfo($this->file['name'], PATHINFO_EXTENSION));
        $filename = $customName ?: (bin2hex(random_bytes(16)) . '.' . $ext);

        $target = $fullPath . $filename;
        if (move_uploaded_file($this->file['tmp_name'], $target)) {
            return rtrim($this->destination, '/') . '/' . $filename;
        }

        $this->errors[] = 'Failed to move uploaded file';
        return null;
    }

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

    public function originalName(): ?string
    {
        return $this->file['name'] ?? null;
    }

    public function size(): ?int
    {
        return $this->file['size'] ?? null;
    }

    public function mimeType(): ?string
    {
        return $this->file['type'] ?? null;
    }
}