<?php

namespace FluxCms\Core\FieldTypes;

class MediaField extends BaseField
{
    protected array $acceptedMimeTypes = ['image/jpeg', 'image/png', 'image/webp'];

    protected bool $multiple = false;

    protected int $maxFiles = 1;

    protected ?string $collection = null;

    protected array $conversions = [];

    protected int $maxFileSize = 10240; // 10MB in KB

    protected bool $showPreview = true;

    public function acceptedMimeTypes(array $mimeTypes): static
    {
        $this->acceptedMimeTypes = $mimeTypes;

        return $this;
    }

    public function multiple(bool $multiple = true, int $maxFiles = 10): static
    {
        $this->multiple = $multiple;
        $this->maxFiles = $maxFiles;

        return $this;
    }

    public function collection(string $collection): static
    {
        $this->collection = $collection;

        return $this;
    }

    public function conversions(array $conversions): static
    {
        $this->conversions = $conversions;

        return $this;
    }

    public function maxFileSize(int $sizeInKb): static
    {
        $this->maxFileSize = $sizeInKb;

        return $this;
    }

    public function showPreview(bool $show = true): static
    {
        $this->showPreview = $show;

        return $this;
    }

    public function images(): static
    {
        $this->acceptedMimeTypes = ['image/jpeg', 'image/png', 'image/webp', 'image/svg+xml'];
        $this->collection = 'images';

        return $this;
    }

    public function documents(): static
    {
        $this->acceptedMimeTypes = [
            'application/pdf',
            'application/msword',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'text/plain',
            'text/csv',
        ];
        $this->collection = 'documents';
        $this->showPreview = false;

        return $this;
    }

    public function videos(): static
    {
        $this->acceptedMimeTypes = ['video/mp4', 'video/webm', 'video/ogg'];
        $this->collection = 'videos';

        return $this;
    }

    public function audio(): static
    {
        $this->acceptedMimeTypes = ['audio/mpeg', 'audio/wav', 'audio/ogg'];
        $this->collection = 'audio';
        $this->showPreview = false;

        return $this;
    }

    public function getType(): string
    {
        return 'media';
    }

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

    public function isMultiple(): bool
    {
        return $this->multiple;
    }

    public function getMaxFiles(): int
    {
        return $this->maxFiles;
    }

    public function getCollection(): ?string
    {
        return $this->collection;
    }

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

    public function getMaxFileSize(): int
    {
        return $this->maxFileSize;
    }

    public function shouldShowPreview(): bool
    {
        return $this->showPreview;
    }

    public function getValidationRules(): array
    {
        $rules = [];

        if ($this->required) {
            $rules[] = 'required';
        }

        if ($this->multiple) {
            $rules[] = 'array';
            $rules[] = "max:{$this->maxFiles}";
            // Each item should be integer (media ID)
            $rules[] = 'array';
            foreach (range(0, $this->maxFiles - 1) as $index) {
                $rules["*.{$index}"] = 'integer|exists:media,id';
            }
        } else {
            $rules[] = 'integer';
            $rules[] = 'exists:media,id';
        }

        return array_merge($rules, $this->rules);
    }

    public function getAcceptAttribute(): string
    {
        return implode(',', $this->acceptedMimeTypes);
    }

    public function isImageType(): bool
    {
        return ! empty(array_filter($this->acceptedMimeTypes, fn ($type) => str_starts_with($type, 'image/')));
    }

    public function isVideoType(): bool
    {
        return ! empty(array_filter($this->acceptedMimeTypes, fn ($type) => str_starts_with($type, 'video/')));
    }

    public function isAudioType(): bool
    {
        return ! empty(array_filter($this->acceptedMimeTypes, fn ($type) => str_starts_with($type, 'audio/')));
    }

    public function isDocumentType(): bool
    {
        return ! empty(array_filter($this->acceptedMimeTypes, fn ($type) => str_starts_with($type, 'application/') || str_starts_with($type, 'text/')
        ));
    }

    public function getValue(array $content, ?string $locale = null): mixed
    {
        $value = parent::getValue($content, $locale);

        // Ensure array for multiple fields
        if ($this->multiple && ! is_array($value)) {
            return $value ? [$value] : [];
        }

        // Ensure integer for single fields
        if (! $this->multiple && is_array($value)) {
            return ! empty($value) ? (int) $value[0] : null;
        }

        return $value;
    }

    public function getMediaItems(mixed $value): \Illuminate\Support\Collection
    {
        if (empty($value)) {
            return collect();
        }

        $mediaIds = is_array($value) ? $value : [$value];
        $mediaIds = array_filter($mediaIds);

        if (empty($mediaIds)) {
            return collect();
        }

        return \Spatie\MediaLibrary\MediaCollections\Models\Media::whereIn('id', $mediaIds)->get();
    }

    public function toArray(): array
    {
        return [
            'type' => $this->getType(),
            'key' => $this->key,
            'label' => $this->label,
            'translatable' => $this->translatable,
            'required' => $this->required,
            'default' => $this->default,
            'acceptedMimeTypes' => $this->acceptedMimeTypes,
            'multiple' => $this->multiple,
            'maxFiles' => $this->maxFiles,
            'collection' => $this->collection,
            'conversions' => $this->conversions,
            'maxFileSize' => $this->maxFileSize,
            'showPreview' => $this->showPreview,
            'helpText' => $this->helpText,
            'attributes' => $this->attributes,
        ];
    }
}
