<?php

namespace App\Http\Resources;

use App\Events\LoadDealershipDataFields;
use App\ImportMaps\VehicleImportMap;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class ImportMapResource extends JsonResource
{
    public static $wrap = '';
    /**
     * Transform the resource into an array.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        $this->resource->load('fields');
        $this->resource->row_data = collect($this->resource->data['row_data'] ?? [])->keys();
        $this->resource->data_options = collect($this->getFieldsForType())
                ->map(fn($value, $key) => [
                    'id' => $key,
                    'name' => "$value ($key) ",
                ])
                ->values();
        $resource = $this->resource->toArray();
        $resource['has_header_row'] = $this->resource->data['has_header_row'] ?? true;
        $resource['clear_previous_entries'] = $this->resource->data['clear_previous_entries'] ?? false;
        $resource['fields'] = $this->mapFields();
        $resource['remote_protocols'] = [
            ['value' => 'ftp', 'label' => 'FTP'],
            ['value' => 'sftp', 'label' => 'SFTP'],
        ];
        $resource['schedule_options'] = [
            ['value' => 'daily', 'label' => 'Daily'],
            ['value' => 'twice_daily', 'label' => 'Twice Daily'],
            ['value' => 'every_two_hours', 'label' => 'Every 2 hours'],
            ['value' => 'hourly', 'label' => 'Hourly'],
        ];
        $resource['dealership_fields'] = $this->getDealershipFields();
        $resource['data']['extra_fields'] = $this->mapExtraFields($resource['data']['extra_fields'] ?? []);
        $resource['data']['automations'] = $resource['data']['automations'] ?? [];
        $resource['remote_files'] = $this->loadRemoteFiles();
        return $resource;
    }

    private function getFieldsForType(): array
    {
        return match ($this->resource->type) {
            'vehicle' => (new VehicleImportMap())->columns(),
            default => [],
        };
    }

    private function getDealershipFields()
    {
        return collect(event(new LoadDealershipDataFields()))
            ->filter()
            ->mapWithKeys(fn($field) => $field)
            ->map(function ($field, $key) {
                $field['id'] = $key;
                return $field;
            })
            ->prepend(['id' => 'location_stock', 'label' => 'Stock location'])
            ->values();
    }

    private function mapFields(): Collection
    {
        return $this->resource->fields->keyBy('on_file')
            ->map(function ($field) {
                $field['required_to_import'] = $field['data']['required_to_import'] ?? false;
                $field['save_on_update'] = $field['data']['save_on_update'] ?? true;
                if (!isset($field['data'])) {
                    $field['data'] = [];
                }
                return $field;
            });
    }

    private function mapExtraFields(array $extraFields = []): array
    {
        return collect($extraFields)
            ->map(function ($extraField) {
                $extraField['save_on_update'] = $extraField['save_on_update'] ?? true;
                return $extraField;
            })
            ->toArray();
    }

    private function loadRemoteFiles(): Collection
    {
        if (empty($this->resource->data['automate'])) {
            return collect();
        }

        try {
            $disk = Storage::build([
                'driver' => $this->resource['data']['protocol'],
                'root' => $this->resource['data']['file_root'] ?? null,
                'host' => $this->resource['data']['host'],
                'username' => $this->resource['data']['username'],
                'password' => $this->resource['data']['password'],
                'throw' => false,
                'timeout' => 2,
            ]);

            return collect($disk->files())
                ->map(fn($file) => [
                    'name' => $file,
                    'size' => $this->fileSize($disk, $file),
                ]);
        } catch (\Exception $exception) {
            return collect();
        }
    }

    private function fileSize($disk, string $file): string
    {
        $kb = $disk->size($file) / 1024;
        if ($kb < 1024) {
            return round($kb) . 'KiB';
        }

        return round($kb / 1024, 1) . 'MiB';
    }
}
