<?php

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

use App\Models\Ecommerce\Product\Property\ProductAttributeValue;
use App\Models\Ecommerce\Product\Property\ProductProperty;
use App\Nova\Forms\NovaForm;
use App\Nova\Resources\Ecommerce\Product\Product\Product as ProductResource;
use App\Nova\Resources\Ecommerce\Product\Product\ProductVariant as ProductVariantResource;
use App\Repositories\Ecommerce\Channel\ChannelRepository;
use App\Repositories\Ecommerce\Collection\CollectionRepository;
use App\Repositories\Ecommerce\Product\Barcode\BarcodeRepository;
use App\Repositories\Ecommerce\Product\Brand\BrandRepository;
use App\Repositories\Ecommerce\Product\Category\CategoryRepository;
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\Boolean;
use Laravel\Nova\Fields\Hidden;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Select;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\Trix;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Panel;
use Nurmuhammet\DynamicFields\DynamicFields;
use Nurmuhammet\InlineRelationship\InlineRelationship;
use Nurmuhammet\ProductInventory\ProductInventory;
use Outl1ne\MultiselectField\Multiselect;

class ProductFieldsForCreate
{
    /**
     * Get the fields for create.
     */
    public static function make(ProductResource $resource, NovaRequest $request): array
    {
        return [
            ID::make()->sortable(),

            new Panel(__('Product relations'), [
                Hidden::make('is_visible')
                    ->default(function () {
                        if (auth()->user()->isEntrepreneur()) {
                            return false;
                        }

                        return true;
                    }),

                Select::make(__('Channel'), 'channel')
                    ->fullWidth()
                    ->displayUsingLabels()
                    ->searchable()
                    ->options(ChannelRepository::values())
                    ->default(tmpostChannel()->id)
                    ->rules('required')
                    ->fillUsing(NovaForm::fillEmpty())
                    ->canSeeWhen('isAdmin', $resource),

                Select::make(__('Brand'), 'brand_id')
                    ->fullWidth()
                    ->displayUsingLabels()
                    ->searchable()
                    ->options(BrandRepository::values())
                    ->rules('nullable'),

                Multiselect::make(__('Category'), 'categories')
                    ->fullWidth()
                    ->options(CategoryRepository::namesWithTaxes())
                    ->help(__('Biggest tax is chosen from categories'))
                    ->rules('required')
                    ->fillUsing(NovaForm::fillEmpty()),

                Multiselect::make(__('Collection'), 'collections')
                    ->fullWidth()
                    ->options(CollectionRepository::values())
                    ->rules('nullable')
                    ->fillUsing(NovaForm::fillEmpty()),
            ]),

            new Panel(__('General information'), [
                Text::make(__('Ady'), 'name')
                    ->fullWidth()
                    ->rules('required', 'string', 'max:255'),

                Trix::make(__('Description'), 'description')
                    ->fullWidth()
                    ->withFiles('public')
                    ->rules('nullable', 'string'),

                Images::make(__('Image'), 'uploads')
                    ->conversionOnIndexView('thumb200x200')
                    ->rules('required')
                    ->setFileName(NovaForm::fillMediaFileName())
                    ->required(),
            ]),

            new Panel(__('Prices'), [
                Text::make(__('Price'), 'cost_amount')
                    ->fullWidth()
                    ->rules('required', 'numeric'),

                Text::make(__('Price without discount'), 'old_price_amount')
                    ->fullWidth()
                    ->rules('nullable', 'numeric', 'gt:readonly_price_amount'),

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

                Hidden::make('price_amount')
                    ->fillUsing(NovaForm::fillAttribute('price_amount', 'readonly_price_amount')),
            ]),

            new Panel(__('Inventory'), [
                Text::make('SKU', 'sku')
                    ->fullWidth()
                    ->rules('nullable', 'string', 'max:255'),

                Boolean::make(__('Generate new barcode'), 'generate_new_barcode')
                    ->onlyOnForms()
                    ->fillUsing(NovaForm::fillEmpty()),

                Text::make(__('Barcode'), 'barcode')
                    ->fullWidth()
                    ->rules('nullable', 'string', 'max:255', 'unique:products,barcode')
                    ->dependsOn(
                        attributes: 'generate_new_barcode',
                        mixin: fn ($field, $request, $formData) => boolval($formData->generate_new_barcode)
                                        ? $field->setValue(BarcodeRepository::generateBarcode())
                                        : null
                    ),

                ProductInventory::make(__('Inventory'), 'inventories')
                    ->fullWidth()
                    ->rules('required')
                    ->dependsOn('channel', NovaProductRepository::inventoryDependsOn('channel'))
                    ->fillUsing(NovaForm::fillEmpty()),

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

                Hidden::make('options')->default(json_encode(ProductRepository::shippingAttributes())),
            ]),

            new Panel(__('Attributes'), [
                DynamicFields::make(__('Attributes'), 'properties')
                    ->fullWidth()
                    ->fillWithArrayName('properties')
                    ->dependsOn(['categories'], NovaProductRepository::createRequestAttributesDependsOn($resource))
                    ->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) {
                            }
                        }
                    }),
            ]),

            new Panel(__('Variations'), [
                // InlineRelationship::make(__('Variations'), 'variations', ProductVariantResource::class)
                // ->hide()
                // ->dependsOn(['categories'], NovaProductRepository::createRequestVariationsDependsOn()),
            ]),
        ];
    }

    /**
     * Register a callback to be called after the resource is created.
     */
    public static function afterCreate(NovaRequest $request, Model $model): void
    {
        $model::withoutEvents(function () use ($request, $model) {
            $user = $request->user();

            $model->categories()->attach($request->input('categories'));
            $model->collections()->attach($request->input('collections'));

            if ($user->isEntrepreneur()) {
                $model->channels()->attach($user->channel()->id);
            } else {
                $model->channels()->attach($request->input('channel'));
            }

            $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,
                ]);
            });
        });
    }
}
