<?php

namespace App\Filament\Pages;

use Filament\Pages\Page;
use App\Models\Product;
use Livewire\WithPagination;

class BulkEditStock extends Page
{
    use WithPagination;

    protected static string $layout = 'filament-panels::components.layout.index';

    protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-pencil-square';

    protected static ?string $title = 'Bulk Edit Stock';

    protected static ?string $navigationLabel = 'Bulk Edit Stock';

    protected static string|\UnitEnum|null $navigationGroup = 'Products';

    protected static ?int $navigationSort = 3;

    protected string $view = 'filament.pages.bulk-edit-stock';

    public string $search = '';

    public int|string $perPage = 15;

    public array $quantities = [];

    public array $securityStocks = [];

    public array $selected = ['product' => [], 'variant' => []];

    public string $bulkQuantityAdjust = '';

    public string $bulkSecurityStockSet = '';

    protected $queryString = [
        'search' => ['except' => ''],
        'perPage' => ['except' => 15],
    ];

    public function updatingSearch(): void
    {
        $this->resetPage();
        $this->selected = ['product' => [], 'variant' => []];
    }

    public function updatingPerPage(): void
    {
        $this->resetPage();
        $this->selected = ['product' => [], 'variant' => []];
    }

    protected function getViewData(): array
    {
        $products = Product::query()
            ->with(['variants'])
            ->when($this->search, function ($query) {
                $query->where(function ($sub) {
                    $sub->where('name', 'like', '%' . $this->search . '%')
                        ->orWhere('sku', 'like', '%' . $this->search . '%')
                        ->orWhereHas('variants', function ($vQuery) {
                            $vQuery->where('sku', 'like', '%' . $this->search . '%');
                        });
                });
            })
            ->paginate($this->perPage === 'all' ? Product::count() : (int) $this->perPage);

        // Pre-fill quantities and security stocks for this page
        foreach ($products as $product) {
            if ($product->variants->isNotEmpty()) {
                foreach ($product->variants as $variant) {
                    if (!isset($this->quantities['variant'][$variant->id])) {
                        $this->quantities['variant'][$variant->id] = $variant->quantity;
                    }
                    if (!isset($this->securityStocks['variant'][$variant->id])) {
                        $this->securityStocks['variant'][$variant->id] = $variant->security_stock ?? 0;
                    }
                }
            } else {
                if (!isset($this->quantities['product'][$product->id])) {
                    $this->quantities['product'][$product->id] = $product->quantity;
                }
                if (!isset($this->securityStocks['product'][$product->id])) {
                    $this->securityStocks['product'][$product->id] = $product->security_stock ?? 0;
                }
            }
        }

        return [
            'products' => $products,
        ];
    }

    public function save(): void
    {
        $this->validate([
            'quantities.product.*' => 'required|integer|min:0',
            'quantities.variant.*' => 'required|integer|min:0',
            'securityStocks.product.*' => 'required|integer|min:0',
            'securityStocks.variant.*' => 'required|integer|min:0',
        ], [
            'quantities.*.*.required' => 'Quantity is required.',
            'quantities.*.*.integer' => 'Quantity must be an integer.',
            'quantities.*.*.min' => 'Quantity cannot be negative.',
            'securityStocks.*.*.required' => 'Security stock is required.',
            'securityStocks.*.*.integer' => 'Security stock must be an integer.',
            'securityStocks.*.*.min' => 'Security stock cannot be negative.',
        ]);

        $updatedCount = 0;

        // 1. Process Variants
        if (isset($this->quantities['variant'])) {
            $variantIds = array_keys($this->quantities['variant']);
            $variants = \App\Models\ProductVariant::whereIn('id', $variantIds)->get();

            foreach ($variants as $variant) {
                $newQty = (int) ($this->quantities['variant'][$variant->id] ?? 0);
                $newSec = (int) ($this->securityStocks['variant'][$variant->id] ?? 0);

                $oldQty = (int) $variant->quantity;
                $oldSec = (int) ($variant->security_stock ?? 0);

                $qtyChanged = $newQty !== $oldQty;
                $secChanged = $newSec !== $oldSec;

                if ($qtyChanged || $secChanged) {
                    if ($secChanged) {
                        $variant->update(['security_stock' => $newSec]);
                    }

                    if ($qtyChanged) {
                        $diff = $newQty - $oldQty;
                        \App\Services\StockAdjustmentService::adjust($variant, $diff, 'manual', [
                            'notes' => 'Bulk adjusted stock via edit grid.',
                            'user_id' => auth()->id(),
                        ]);

                        // Sync parent product quantity
                        $parent = $variant->product;
                        if ($parent) {
                            \App\Services\StockAdjustmentService::adjust($parent, $diff, 'manual', [
                                'notes' => 'Bulk adjusted variant stock via edit grid.',
                                'user_id' => auth()->id(),
                            ]);
                        }
                    }

                    $updatedCount++;
                }
            }
        }

        // 2. Process Simple Products
        if (isset($this->quantities['product'])) {
            $productIds = array_keys($this->quantities['product']);
            $products = \App\Models\Product::whereIn('id', $productIds)->get();

            foreach ($products as $product) {
                $newQty = (int) ($this->quantities['product'][$product->id] ?? 0);
                $newSec = (int) ($this->securityStocks['product'][$product->id] ?? 0);

                $oldQty = (int) $product->quantity;
                $oldSec = (int) ($product->security_stock ?? 0);

                $qtyChanged = $newQty !== $oldQty;
                $secChanged = $newSec !== $oldSec;

                if ($qtyChanged || $secChanged) {
                    if ($secChanged) {
                        $product->update(['security_stock' => $newSec]);
                    }

                    if ($qtyChanged) {
                        $diff = $newQty - $oldQty;
                        \App\Services\StockAdjustmentService::adjust($product, $diff, 'manual', [
                            'notes' => 'Bulk adjusted stock via edit grid.',
                            'user_id' => auth()->id(),
                        ]);
                    }

                    $updatedCount++;
                }
            }
        }

        if ($updatedCount > 0) {
            \Filament\Notifications\Notification::make()
                ->title('Inventory Updated')
                ->body("Successfully updated stock levels for {$updatedCount} items.")
                ->success()
                ->send();
        } else {
            \Filament\Notifications\Notification::make()
                ->title('No Changes')
                ->body('No inventory modifications were detected.')
                ->info()
                ->send();
        }

        // Reset inputs to re-fetch clean database values
        $this->quantities = [];
        $this->securityStocks = [];

        $this->dispatch('saved');
    }

    public function toggleSelectAllPage(bool $checked): void
    {
        $products = Product::query()
            ->with(['variants'])
            ->when($this->search, function ($query) {
                $query->where(function ($sub) {
                    $sub->where('name', 'like', '%' . $this->search . '%')
                        ->orWhere('sku', 'like', '%' . $this->search . '%')
                        ->orWhereHas('variants', function ($vQuery) {
                            $vQuery->where('sku', 'like', '%' . $this->search . '%');
                        });
                });
            })
            ->paginate($this->perPage === 'all' ? Product::count() : (int) $this->perPage);

        foreach ($products as $product) {
            if ($product->variants->isNotEmpty()) {
                foreach ($product->variants as $variant) {
                    $this->selected['variant'][$variant->id] = $checked;
                }
            } else {
                $this->selected['product'][$product->id] = $checked;
            }
        }
    }

    public function getSelectedCount(): int
    {
        $count = 0;
        if (!empty($this->selected['product'])) {
            $count += count(array_filter($this->selected['product']));
        }
        if (!empty($this->selected['variant'])) {
            $count += count(array_filter($this->selected['variant']));
        }
        return $count;
    }

    public function applyBulkQuantityAdjust(): void
    {
        if (empty($this->bulkQuantityAdjust)) {
            return;
        }

        $adjustValue = $this->bulkQuantityAdjust;
        $isRelative = str_starts_with($adjustValue, '+') || str_starts_with($adjustValue, '-');
        $numericValue = (int) $adjustValue;

        $updatedCount = 0;

        // 1. Process selected variants
        if (!empty($this->selected['variant'])) {
            foreach ($this->selected['variant'] as $id => $selected) {
                if (!$selected) continue;

                $variant = \App\Models\ProductVariant::find($id);
                if (!$variant) continue;

                $currentVal = isset($this->quantities['variant'][$id]) 
                    ? (int)$this->quantities['variant'][$id] 
                    : (int)$variant->quantity;

                $newVal = $isRelative ? ($currentVal + $numericValue) : $numericValue;
                $this->quantities['variant'][$id] = max(0, $newVal);
                $updatedCount++;
            }
        }

        // 2. Process selected products
        if (!empty($this->selected['product'])) {
            foreach ($this->selected['product'] as $id => $selected) {
                if (!$selected) continue;

                $product = \App\Models\Product::find($id);
                if (!$product) continue;

                $currentVal = isset($this->quantities['product'][$id]) 
                    ? (int)$this->quantities['product'][$id] 
                    : (int)$product->quantity;

                $newVal = $isRelative ? ($currentVal + $numericValue) : $numericValue;
                $this->quantities['product'][$id] = max(0, $newVal);
                $updatedCount++;
            }
        }

        if ($updatedCount > 0) {
            \Filament\Notifications\Notification::make()
                ->title('Applied Bulk Quantity')
                ->body("Updated inline quantities for {$updatedCount} selected items. Review and click Save Changes.")
                ->success()
                ->send();
        }

        $this->selected = ['product' => [], 'variant' => []];
        $this->bulkQuantityAdjust = '';
    }

    public function applyBulkSecurityStockSet(): void
    {
        if (empty($this->bulkSecurityStockSet)) {
            return;
        }

        $newSecStock = max(0, (int) $this->bulkSecurityStockSet);
        $updatedCount = 0;

        // 1. Process selected variants
        if (!empty($this->selected['variant'])) {
            foreach ($this->selected['variant'] as $id => $selected) {
                if (!$selected) continue;
                $this->securityStocks['variant'][$id] = $newSecStock;
                $updatedCount++;
            }
        }

        // 2. Process selected products
        if (!empty($this->selected['product'])) {
            foreach ($this->selected['product'] as $id => $selected) {
                if (!$selected) continue;
                $this->securityStocks['product'][$id] = $newSecStock;
                $updatedCount++;
            }
        }

        if ($updatedCount > 0) {
            \Filament\Notifications\Notification::make()
                ->title('Applied Bulk Safety Stock')
                ->body("Set inline safety stock to {$newSecStock} for {$updatedCount} selected items. Review and click Save Changes.")
                ->success()
                ->send();
        }

        $this->selected = ['product' => [], 'variant' => []];
        $this->bulkSecurityStockSet = '';
    }
}
