<?php

namespace App\Filament\Resources\OrderResource\Pages;

use App\Filament\Resources\OrderResource;
use App\Filament\Resources\OrderResource\Widgets\OrdersByCarrierWidget;
use App\Filament\Resources\OrderResource\Widgets\OrdersByChannelWidget;
use App\Filament\Resources\OrderResource\Widgets\OrdersByPaymentWidget;
use App\Filament\Resources\OrderResource\Widgets\OrdersByProvinceWidget;
use App\Filament\Resources\OrderResource\Widgets\OrdersByStatusWidget;
use App\Filament\Resources\OrderResource\Widgets\OrdersByStoreWidget;
use App\Filament\Resources\OrderResource\Widgets\OrdersByTypeWidget;
use App\Filament\Resources\OrderResource\Widgets\OrdersAnnualReportsTitleWidget;
use App\Models\Order;
use App\Models\Universal\UniversalOrder;
use App\Models\UniversalOrderImport;
use App\Services\UniversalOrdersImportService;
use Filament\Actions;
use Filament\Forms\Components\Select;
use Filament\Notifications\Notification;
use Filament\Resources\Components\Tab;
use Filament\Resources\Pages\ListRecords;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Support\HtmlString;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Database\Eloquent\Builder;
use App\Enums\OrderType as OrderTypeEnum;
use App\Models\OrderTypeCatalog;

class ListOrders extends ListRecords
{
    protected static string $resource = OrderResource::class;

    public int $countsYear;

    public function mount(): void
    {
        parent::mount();
        $this->countsYear = (int) session()->get('orders.counts_year', now()->year);

        $this->autoImportUniversalOrders();
    }

    private function autoImportUniversalOrders(): void
    {
        Log::info('Entered autoImportUniversalOrders', [
            'enabled' => (bool) env('UNIVERSAL_AUTO_IMPORT_ON_VISIT', app()->environment('local')),
        ]);

        $enabled = (bool) env('UNIVERSAL_AUTO_IMPORT_ON_VISIT', app()->environment('local'));
        if (! $enabled) {
            return;
        }

        $throttleSeconds = (int) env('UNIVERSAL_IMPORT_THROTTLE_SECONDS', 60);
        $limit = (int) env('UNIVERSAL_IMPORT_LIMIT', 200);

        if ($limit <= 0) {
            return;
        }

        $lockKey = 'universal.import.orders.on_visit';
        if (! Cache::add($lockKey, now()->toIso8601String(), $throttleSeconds)) {
            return;
        }

        try {
            $window = (int) env('UNIVERSAL_IMPORT_SYNC_WINDOW', 500);
            if ($window <= 0) {
                $window = 500;
            }

            // Trae una ventana reciente y detecta faltantes por tracking local.
            // Esto evita quedar “atascados” si el max(universal_order_id) es mayor
            // que el set actual o si existen huecos en los IDs.
            $recent = UniversalOrder::query()
                ->orderByDesc('id_order')
                ->limit(max($window, $limit))
                ->get();

            if ($recent->isEmpty()) {
                return;
            }

            $recentIds = $recent
                ->pluck('id_order')
                ->map(fn ($v) => (int) $v)
                ->filter(fn ($v) => $v > 0)
                ->values();

            $alreadyImported = UniversalOrderImport::query()
                ->whereIn('universal_order_id', $recentIds->all())
                ->pluck('universal_order_id')
                ->map(fn ($v) => (int) $v)
                ->all();

            $importedLookup = array_fill_keys($alreadyImported, true);

            $orders = $recent
                ->reject(fn ($o) => isset($importedLookup[(int) ($o->id_order ?? 0)]))
                ->sortBy('id_order')
                ->take($limit);

            if ($orders->isEmpty()) {
                return;
            }

            /** @var UniversalOrdersImportService $importer */
            $importer = app(UniversalOrdersImportService::class);

            $importedCount = 0;
            foreach ($orders as $universalOrder) {
                $importer->importOrder($universalOrder);
                $importedCount++;
            }

            Notification::make()
                ->title('Órdenes sincronizadas')
                ->body("Se importaron {$importedCount} órdenes desde Universal.")
                ->success()
                ->send();
        } catch (\Throwable $e) {
            Log::warning('Universal auto import failed', [
                'exception' => $e::class,
                'message' => $e->getMessage(),
            ]);

            Notification::make()
                ->title('No se pudo sincronizar Universal')
                ->body($e->getMessage())
                ->warning()
                ->send();
        }
    }

    public function getHeading(): string | Htmlable
    {
        $icon = static::$resource::getNavigationIcon();

        if (blank($icon)) {
            return parent::getHeading();
        }

        return new HtmlString(
            view('filament.module-heading', [
                'icon' => $icon,
                'heading' => parent::getHeading(),
            ])->render(),
        );
    }

    public function getSubheading(): ?string
    {
        return static::$resource::getModuleDescription();
    }

    protected function getHeaderActions(): array
    {
        return [
            Actions\CreateAction::make()->icon('heroicon-m-plus'),
            Actions\Action::make('set_counts_year')
                ->label(fn (): string => "Año conteos: {$this->countsYear}")
                ->icon('heroicon-o-calendar-days')
                ->form([
                    Select::make('year')
                        ->label('Año')
                        ->options(function (): array {
                            $years = Order::query()
                                ->selectRaw('YEAR(date_order) as y')
                                ->distinct()
                                ->orderByDesc('y')
                                ->pluck('y', 'y')
                                ->all();

                            $current = now()->year;
                            $years[$current] = $years[$current] ?? $current;

                            krsort($years);

                            return $years;
                        })
                        ->default(fn () => $this->countsYear)
                        ->required(),
                ])
                ->action(function (array $data): void {
                    $this->countsYear = (int) $data['year'];
                    session()->put('orders.counts_year', $this->countsYear);
                }),
        ];
    }

    protected function getFooterWidgets(): array
    {
        return [
            OrdersAnnualReportsTitleWidget::class,
            OrdersByStatusWidget::class,
            OrdersByTypeWidget::class,
            OrdersByChannelWidget::class,
            OrdersByCarrierWidget::class,
            OrdersByPaymentWidget::class,
            OrdersByProvinceWidget::class,
            OrdersByStoreWidget::class,
        ];
    }

    public function getFooterWidgetsColumns(): int | array
    {
        return 1;
    }

    /** @return array<string, Tab> */
    public function getTabs(): array
    {
        $reshipmentTypeId = $this->reshipmentTypeId();

        return [
            'todas' => Tab::make('Todas'),

            'universal' => Tab::make('Órdenes Universal')
                ->modifyQueryUsing(fn (Builder $query) => $this->applyUniversalImportedFilter($query)),

            'redespachos' => Tab::make('Redespachos')
                ->modifyQueryUsing(function (Builder $query) use ($reshipmentTypeId) {
                    return $query->where(function (Builder $q) use ($reshipmentTypeId): void {
                        if ($reshipmentTypeId > 0) {
                            $q->where('order_type_id', $reshipmentTypeId);
                            return;
                        }

                        $q->where('order_type', OrderTypeEnum::Reshipment->value);
                    });
                }),

            'picking' => Tab::make('Pendientes de Picking')
                ->modifyQueryUsing(fn (Builder $query) => $query->where('status_id', 1)),
        ];
    }

    private function applyUniversalImportedFilter(Builder $query): Builder
    {
        // Nota: No usamos remote_order_id porque en tbl_orders existe un unique
        // (y el importador puede crear órdenes derivadas por sucursal).
        // El tracking oficial de importación está en tbl_universal_order_imports.

        return $query->where(function (Builder $q): void {
            $q->whereExists(function ($sq): void {
                $sq->selectRaw('1')
                    ->from('tbl_universal_order_imports as u')
                    ->whereColumn('u.order_reference', 'tbl_orders.order_reference');
            })->orWhereExists(function ($sq): void {
                $sq->selectRaw('1')
                    ->from('tbl_universal_order_imports as u')
                    ->whereColumn('u.order_reference', 'tbl_orders.original_order_reference');
            });
        });
    }

    private function reshipmentTypeId(): int
    {
        static $cached = null;

        if ($cached !== null) {
            return (int) $cached;
        }

        $cached = (int) (OrderTypeCatalog::query()
            ->where('code', OrderTypeEnum::Reshipment->value)
            ->value('id_order_type') ?? 0);

        return (int) $cached;
    }
}
