<?php

namespace App\Nova\Resources\Ecommerce\Product\Product\Concerns\Variant;

use App\Models\Ecommerce\Product\Inventory\Inventory;
use App\Models\Ecommerce\Product\Product\Product as ProductModel;
use App\Models\Ecommerce\Product\Property\ProductAttributeValue;
use App\Models\Ecommerce\Product\Property\ProductProperty;
use App\Nova\Forms\NovaForm;
use App\Repositories\Ecommerce\Product\NovaProductRepository;
use App\Repositories\Ecommerce\Product\ProductRepository;
use Ebess\AdvancedNovaMediaLibrary\Fields\Images;
use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Laravel\Nova\Fields\Heading;
use Laravel\Nova\Fields\Hidden;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Number;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Http\Requests\NovaRequest;
use Nurmuhammet\DynamicFields\DynamicFields;
use Nurmuhammet\ProductInventory\ProductInventory;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class VariantFieldsForCreate
{
    /**
     * Get the fields for create.
     */
    public static function make(NovaRequest $request): array
    {
        if ($request->viaRelationship()) {
            $parent = ProductModel::find($request->viaResourceId);
            $categories = $parent->categories;
        } else {
            $parent = null;
            $categories = session('product_categories') ?? [];
        }

        return [
            ID::make()->sortable(),

            ProductInventory::make(__('Inventory'), 'inventories')
                ->rules('required')
                ->options(Inventory::pluck('name', 'id'))
                ->fillUsing(NovaForm::fillEmpty()),

            DynamicFields::make('Attributes', 'properties')
                ->fillWithArrayName('properties')
                ->fields(fn () => NovaProductRepository::attributeFields($categories))
                ->fillUsing(function ($request, $model, $attribute, $requestAttribute) {
                    $properties = $request->input('properties');

                    foreach ($properties as $key => $value) {
                        try {
                            if (in_array($key, ['size', 'colour'])) {
                                $model->{$key} = $value;
                            }
                        } catch (Exception) {
                        }
                    }
                }),

            Heading::make(__('Leave empty to use original image')),
            Images::make(__('Image'), 'uploads')
                ->conversionOnIndexView('thumb150x150')
                ->showStatistics()
                ->help(__('Leave empty to use original image')),

            Text::make(__('Price'), 'cost_amount')
                ->default(optional($parent)->cost_amount)
                ->rules('nullable', 'numeric'),

            Text::make(__('Price without discount'), 'old_price_amount')
                ->default(optional($parent)->old_price_amount)
                ->rules('nullable', 'numeric'),

            Text::make(__('Purchase price'), 'readonly_price_amount')
                ->readonly()
                ->dependsOn(['cost_amount'], NovaProductRepository::priceAmountDependsOn($categories)),

            Hidden::make('price_amount')
                ->fillUsing(function ($request, $model, $attribute, $requestAttribute) {
                    $model->{$attribute} = $request->input('readonly_price_amount');
                }),

            Text::make('SKU', 'sku')
                ->rules('nullable', 'string', 'max:255'),

            Number::make(__('Security stock'), 'security_stock')
                ->rules('nullable', 'integer'),

            Hidden::make('name')
                ->default($parent->name ?? 'inlineCreated'),

            Hidden::make('options')
                ->fillUsing(function ($request, $model, $attribute, $requestAttribute) {
                    if ($request->name === 'inlineCreated') {
                        $model->options->set('inline_created', true);
                    } else {
                        json_encode(ProductRepository::shippingAttributes());
                    }
                }),

            Hidden::make('stock')
                ->fillUsing(function ($request, $model, $attribute, $requestAttribute) {
                    $model->{$attribute} = array_sum(array_values($request->input('inventories')));
                }),
        ];
    }

    /**
     * After resource has been created
     */
    public static function afterCreate(NovaRequest $request, Model $model): void
    {
        $model::withoutEvents(function () use ($request, $model) {
            if ($request->viaRelationship() && $request->missing('__media__')) {
                $parent = ProductModel::find($request->viaResourceId);

                $parent->media->each(function (Media $media) use ($model) {
                    $model->addMedia($media->getPath())
                        ->preservingOriginal()
                        ->toMediaCollection($media->collection_name);
                });
            }

            $request->collect('inventories')->each(
                fn ($stockValue, $inventoryID) => $model->inventories()->attach($inventoryID, ['stock' => $stockValue])
            );

            $properties = $request->input('properties');
            $attribute_ids = $properties
                        ? DB::table('attributes')->whereIn('slug', array_keys($properties))->get(['id', 'type', 'slug'])
                        : collect();

            $attribute_ids->each(function ($attribute) use ($model, $properties) {
                $productAttribute = ProductProperty::create([
                    'product_id' => $model->id,
                    'attribute_id' => $attribute->id,
                ]);

                ProductAttributeValue::create([
                    'product_attribute_id' => $productAttribute->id,
                    'attribute_value_id' => in_array($attribute->type, ['text', 'number']) ? null : $properties[$attribute->slug],
                    'product_custom_value' => in_array($attribute->type, ['text', 'number']) ? $properties[$attribute->slug] : null,
                ]);
            });
        });
    }
}
