<?php

namespace App\Filament\Tenant\Pages;

use App\Models\Tenant\Part;
use App\Models\Tenant\Purchase;
use App\Models\Tenant\PurchaseItem;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Livewire\Attributes\On;

/**
 * Mobile scanner: opens camera in the browser, decodes QR/barcode, looks up
 * Part by:
 *   - `PART:<article|id>` payload (our own QR labels)
 *   - exact barcode match on parts.barcode
 *   - exact article match on parts.article
 * On match → redirect to Part edit page.
 */
class Scanner extends Page
{
    protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-qr-code';

    protected static ?string $navigationLabel = 'Scaner';

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

    protected static ?int $navigationSort = 39;

    protected static ?string $title = 'Scaner cod QR / Bare';

    protected string $view = 'filament.tenant.pages.scanner';

    public string $manual = '';
    public ?int $purchaseId = null;
    public array $receivedToasts = [];

    public function mount(): void
    {
        // Optional ?purchase=N → receipt mode: scans mark items received
        $purchase = request()->query('purchase');
        if ($purchase && ctype_digit((string) $purchase)) {
            $this->purchaseId = (int) $purchase;
        }
    }

    public function getActivePurchase(): ?Purchase
    {
        return $this->purchaseId ? Purchase::find($this->purchaseId) : null;
    }

    public function getPendingItems(): array
    {
        if (! $this->purchaseId) return [];
        return PurchaseItem::where('purchase_id', $this->purchaseId)
            ->whereColumn('qty_received', '<', 'qty')
            ->orderBy('article')
            ->get(['id', 'article', 'name', 'qty', 'qty_received'])
            ->toArray();
    }

    #[On('scanner-decoded')]
    public function decoded(string $text): void
    {
        $this->process(trim($text));
    }

    public function submitManual(): void
    {
        if (trim($this->manual) === '') return;
        $this->process(trim($this->manual));
        $this->manual = '';
    }

    protected function process(string $code): void
    {
        // Receipt mode: increment qty_received on matching purchase item
        if ($this->purchaseId) {
            $this->markReceivedByScan($code);
            return;
        }
        $this->resolveAndRedirect($code);
    }

    protected function markReceivedByScan(string $code): void
    {
        $clean = str_starts_with($code, 'PART:') ? substr($code, 5) : $code;

        $item = PurchaseItem::where('purchase_id', $this->purchaseId)
            ->whereColumn('qty_received', '<', 'qty')
            ->where(function ($q) use ($clean, $code) {
                $q->where('article', $clean)->orWhere('article', $code);
            })
            ->first();

        if (! $item) {
            Notification::make()
                ->title('Articol nu se potrivește comenzii')
                ->body('Codul ' . $code . ' nu apare în liniile neîncasate ale acestei comenzi.')
                ->warning()->send();
            return;
        }

        $item->qty_received = min((float) $item->qty, (float) $item->qty_received + 1);
        $item->save();

        $this->receivedToasts[] = [
            'article' => $item->article,
            'name' => $item->name,
            'qty_received' => (float) $item->qty_received,
            'qty_total' => (float) $item->qty,
            'at' => now()->format('H:i:s'),
        ];

        Notification::make()
            ->title("+1 {$item->article} — {$item->qty_received}/{$item->qty}")
            ->success()->send();
    }

    protected function resolveAndRedirect(string $code): void
    {
        $clean = $code;
        if (str_starts_with($clean, 'PART:')) {
            $clean = substr($clean, 5);
        }

        $part = Part::where(function ($q) use ($clean, $code) {
                $q->where('article', $clean)
                  ->orWhere('barcode', $clean)
                  ->orWhere('barcode', $code);
                if (ctype_digit($clean)) $q->orWhere('id', (int) $clean);
            })
            ->first();

        if (! $part) {
            Notification::make()
                ->title('Cod necunoscut')
                ->body('Nu am găsit nicio piesă pentru: ' . $code)
                ->warning()
                ->send();
            return;
        }

        Notification::make()
            ->title('Piesă găsită: ' . $part->name)
            ->success()
            ->send();

        $this->redirect(
            route('filament.tenant.resources.parts.edit', ['record' => $part->id])
        );
    }
}
