<?php

namespace Daylight\Core\Livewire\Store;

use Daylight\Core\Livewire\Tables\BaseTable;
use Daylight\Core\Livewire\Tables\Concerns\WithBulkActions;
use Daylight\Core\Livewire\Tables\Concerns\WithFiltering;
use Daylight\Core\Livewire\Tables\Concerns\WithRowActions;
use Daylight\Core\Livewire\Tables\Concerns\WithSearch;
use Daylight\Core\Livewire\Tables\Concerns\WithSorting;
use Daylight\Core\Models\Enums\ProductStatus;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
use Livewire\Attributes\Computed;

class ProductTable extends BaseTable
{
    use WithBulkActions;
    use WithFiltering;
    use WithRowActions;
    use WithSearch;
    use WithSorting;

    protected function getBaseQuery(): Builder
    {
        return (daylightModel('product'))::query()->latest();
    }

    protected function applySearch(Builder $query, ?string $searchQuery): Builder
    {
        return $query->when($searchQuery, function ($query, $searchQuery) {
            $query
                ->whereHas('translations', function ($query) use ($searchQuery) {
                    $query->where('name', 'like', "%{$searchQuery}%");
                })
                ->orWhereHas('variants', function ($query) use ($searchQuery) {
                    $query->where('sku', 'like', "%{$searchQuery}%");
                });
        });
    }

    protected function sortableColumns(): array
    {
        return ['name', 'status', 'created_at'];
    }

    protected function applySorting(Builder $query): Builder
    {
        if ($this->sortField === 'name') {
            return $query->orderBy(
                (daylightModel('product_translation'))::select('name')
                    ->whereColumn('product_id', 'products.id')
                    ->where('locale', app()->getLocale())
                    ->limit(1),
                $this->sortDirection
            );
        }

        return $query->orderBy($this->sortField, $this->sortDirection);
    }

    protected function applyFilter(Builder $query, string $name, mixed $value): Builder
    {
        return match ($name) {
            'status' => $query->where('status', $value),
            default => $query,
        };
    }

    protected function availableFilters(): array
    {
        return [
            'status' => [
                'label' => __('daylight::general.all_statuses'),
                'options' => ProductStatus::formattedValues()->toArray(),
            ],
        ];
    }

    #[Computed]
    protected function availableBulkActions(): array
    {
        return [
            'bulk_delete' => [
                'name' => __('daylight::general.delete'),
                'action' => 'bulkDelete',
                'confirm' => true,
            ],
            'bulk_publish' => [
                'name' => __('daylight::general.published'),
                'action' => 'bulkPublish',
            ],
            'bulk_draft' => [
                'name' => __('daylight::general.draft'),
                'action' => 'bulkDraft',
            ],
            'bulk_inactive' => [
                'name' => __('daylight::general.inactive'),
                'action' => 'bulkInactive',
            ],
        ];
    }

    public function bulkPublish(): void
    {
        $this->bulkStatusChange(ProductStatus::PUBLISHED->value);
    }

    public function bulkDraft(): void
    {
        $this->bulkStatusChange(ProductStatus::DRAFT->value);
    }

    public function bulkInactive(): void
    {
        $this->bulkStatusChange(ProductStatus::INACTIVE->value);
    }

    protected function performDuplicate($model)
    {
        $model->load([
            'translations',
            'media',
            'variants.optionValues',
            'variants.media',
            'variants.prices',
            'options.values.translations',
            'options.translations',
            'categories',
            'labels',
            'attributeValues',
        ]);

        return DB::transaction(function () use ($model) {
            $newProduct = $model->replicate();
            $newProduct->status = ProductStatus::DRAFT;
            $newProduct->save();

            // Copy translations
            foreach ($model->translations as $translation) {
                $newTranslation = $translation->replicate();
                $newTranslation->product_id = $newProduct->id;
                $newTranslation->name = __('daylight::content.copy_of', ['name' => $translation->name]);
                $newTranslation->slug = null;
                $newTranslation->save();
            }

            // Sync category, label, and attribute value pivots
            $newProduct->categories()->sync($model->categories->pluck('id'));
            $newProduct->labels()->sync($model->labels->pluck('id'));
            $newProduct->attributeValues()->sync($model->attributeValues->pluck('id'));

            // Copy media through morphToMany pivots
            foreach ($model->media as $media) {
                $newProduct->media()->attach($media->id, [
                    'properties' => $media->pivot->properties,
                    'order' => $media->pivot->order,
                ]);
            }

            // Build a map from old option value IDs to new option value IDs
            $optionValueMap = [];

            // Copy options + values + translations
            foreach ($model->options as $option) {
                $newOption = $option->replicate();
                $newOption->product_id = $newProduct->id;
                $newOption->save();

                foreach ($option->translations as $translation) {
                    $newTranslation = $translation->replicate();
                    $newTranslation->option_id = $newOption->id;
                    $newTranslation->save();
                }

                foreach ($option->values as $value) {
                    $newValue = $value->replicate();
                    $newValue->option_id = $newOption->id;
                    $newValue->save();

                    $optionValueMap[$value->id] = $newValue->id;

                    foreach ($value->translations as $translation) {
                        $newTranslation = $translation->replicate();
                        $newTranslation->option_value_id = $newValue->id;
                        $newTranslation->save();
                    }
                }
            }

            // Copy variants with new SKU, option values, media, and prices
            foreach ($model->variants as $variant) {
                $newVariant = $variant->replicate();
                $newVariant->product_id = $newProduct->id;
                $newVariant->sku = "{$variant->sku}-copy";
                $newVariant->save();

                // Map old option value IDs to new ones
                $newOptionValueIds = $variant->optionValues
                    ->pluck('id')
                    ->map(fn ($id) => $optionValueMap[$id] ?? $id)
                    ->toArray();
                $newVariant->optionValues()->sync($newOptionValueIds);

                // Copy variant media
                foreach ($variant->media as $media) {
                    $newVariant->media()->attach($media->id, [
                        'properties' => $media->pivot->properties,
                        'order' => $media->pivot->order,
                    ]);
                }

                // Copy variant prices
                foreach ($variant->prices as $price) {
                    $newPrice = $price->replicate();
                    $newPrice->variant_id = $newVariant->id;
                    $newPrice->save();
                }
            }

            return $newProduct;
        });
    }

    protected function getEditRoute($model): string
    {
        return route('daylight.store.products.edit', $model);
    }

    public function render(): View
    {
        return view('daylight::livewire.store.product-table');
    }
}
