<?php
namespace EasyChat\Library\Attachment;

use EasyChat\Library\AttachmentPolicy;
use EasyChat\Library\AttachmentStorage;
use EasyChat\Library\Messenger\AttachmentCapabilities;






class AttachmentBatchUploadService {
    private $storage;

    public function __construct(AttachmentStorage $storage) {
        $this->storage = $storage;
    }

    public function save(int $chat_id, array $file_fields, int $max_mb, string $prefix, string $provider): array {
        $files = self::normalizeFiles($file_fields);
        $capabilities = AttachmentCapabilities::forProvider($provider);
        $limit = max(0, (int)($capabilities['max_attachments'] ?? 0));
        if (!$files) {
            return ['success' => false, 'error' => 'file_missing'];
        }
        if ($limit <= 0 || count($files) > $limit) {
            return ['success' => false, 'error' => 'too_many_attachments', 'limit' => $limit];
        }

        $uploads = [];
        foreach ($files as $file) {
            $upload = $this->storage->saveUploadedAttachment($chat_id, $file, $max_mb, $prefix);
            if (empty($upload['success'])) {
                $cleanup_complete = $this->discard($chat_id, $uploads);
                return [
                    'success' => false,
                    'error' => $cleanup_complete
                        ? (string)($upload['error'] ?? 'file_denied')
                        : 'file_save_failed',
                ];
            }
            if (!$this->isFormatAllowed($upload, $capabilities)) {
                $uploads[] = $upload;
                return [
                    'success' => false,
                    'error' => $this->discard($chat_id, $uploads)
                        ? 'attachment_format_not_supported'
                        : 'file_save_failed',
                ];
            }
            $uploads[] = $upload;
        }

        $kinds = array_values(array_unique(array_map(function(array $upload): string {
            return (string)($upload['kind'] ?? 'image');
        }, $uploads)));
        $document_count = count(array_filter($uploads, function(array $upload): bool {
            return (string)($upload['kind'] ?? 'image') === 'document';
        }));
        if (in_array('image', $kinds, true) && empty($capabilities['images'])) {
            return [
                'success' => false,
                'error' => $this->discard($chat_id, $uploads)
                    ? 'attachment_type_unsupported'
                    : 'file_save_failed',
            ];
        }
        if (in_array('document', $kinds, true) && empty($capabilities['documents'])) {
            return [
                'success' => false,
                'error' => $this->discard($chat_id, $uploads)
                    ? 'attachment_type_unsupported'
                    : 'file_save_failed',
            ];
        }
        if (count($kinds) > 1 && isset($capabilities['mixed_image_document']) && !$capabilities['mixed_image_document']) {
            return [
                'success' => false,
                'error' => $this->discard($chat_id, $uploads)
                    ? 'mixed_attachments_unsupported'
                    : 'file_save_failed',
            ];
        }
        $max_documents = isset($capabilities['max_documents']) ? (int)$capabilities['max_documents'] : $limit;
        if ($document_count > $max_documents) {
            return [
                'success' => false,
                'error' => $this->discard($chat_id, $uploads)
                    ? 'too_many_documents'
                    : 'file_save_failed',
                'limit' => $max_documents,
            ];
        }

        return ['success' => true, 'uploads' => $uploads, 'limit' => $limit];
    }

    public static function normalizeFiles(array $file_fields): array {
        $normalized = [];
        foreach ($file_fields as $field) {
            if (!is_array($field) || !isset($field['name'])) {
                continue;
            }
            if (!is_array($field['name'])) {
                if ((string)$field['name'] !== '') {
                    $normalized[] = $field;
                }
                continue;
            }
            foreach ($field['name'] as $index => $name) {
                if ((string)$name === '') {
                    continue;
                }
                $normalized[] = [
                    'name' => $name,
                    'type' => $field['type'][$index] ?? '',
                    'tmp_name' => $field['tmp_name'][$index] ?? '',
                    'error' => $field['error'][$index] ?? UPLOAD_ERR_NO_FILE,
                    'size' => $field['size'][$index] ?? 0,
                ];
            }
        }
        return $normalized;
    }

    private function discard(int $chat_id, array $uploads): bool {
        $removed = true;
        foreach ($uploads as $upload) {
            if (!$this->storage->discardPendingUpload($chat_id, $upload)) {
                $removed = false;
            }
        }
        return $removed;
    }

    private function isFormatAllowed(array $upload, array $capabilities): bool {
        $kind = (string)($upload['kind'] ?? 'image');
        $filename = (string)($upload['original_name'] ?? $upload['display_name'] ?? $upload['filename'] ?? '');
        $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
        if ($extension === '') {
            $extension = AttachmentPolicy::extensionForMime((string)($upload['mime'] ?? ''));
        }

        $key = $kind === 'document' ? 'document_extensions' : 'image_extensions';
        $fallback = $kind === 'document'
            ? AttachmentPolicy::allowedDocumentExtensions()
            : AttachmentPolicy::allowedImageExtensions();
        $allowed = is_array($capabilities[$key] ?? null) ? $capabilities[$key] : $fallback;
        $allowed = array_values(array_filter(array_map(function ($value): string {
            return strtolower(ltrim(trim((string)$value), '.'));
        }, $allowed)));

        return $extension !== '' && in_array($extension, $allowed, true);
    }
}
