<?php

namespace App\Filament\Pages;

use App\Models\Item;
use App\Models\ItemCharacteristic;
use App\Models\Machine;
use App\Models\Plant;
use App\Models\ProductionOrder;
use App\Models\StickerDetail;
use App\Models\StickerMappingMaster;
use App\Models\StickerStructureDetail;
use App\Models\StickerValidation;
use App\Services\StickerPdfService;
use Filament\Facades\Filament;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;

class StickerPrint extends Page implements HasForms
{
    protected static ?string $navigationIcon = 'heroicon-o-document-text';

    protected static string $view = 'filament.pages.sticker-print';

    protected static ?string $navigationGroup = 'Customized Sticker Printing';

    public array $filters = [];

    public $serNo;

    public $ref_number;

    //public $workCenter;

    public function form(Form $form): Form
    {
        return $form
            ->statePath('filters')
            ->schema([
                Section::make('')
                    ->schema([
                        Select::make('plant_id')
                            ->label('Plant')
                            ->reactive()
                            ->options(function(){

                                $plantId = Filament::auth()->user()->plant_id;

                                return $plantId
                                    ? Plant::where('id',$plantId)
                                        ->pluck('name','id')
                                    : Plant::pluck('name','id');

                            })
                            ->required(),
                        Select::make('machine_id')
                            ->label('Work Center')
                            ->reactive()
                            ->options(function(callable $get){

                                $plantId = $get('plant_id');
                                    if (empty($plantId)) {
                                        return [];
                                    }
                                    return Machine::where('plant_id', $plantId)->pluck('work_center', 'id');

                            })
                            ->required(),
                        TextInput::make('production_order')
                            ->label('Production Order')
                            ->reactive()
                            ->required(),
                        TextInput::make('serial_number')
                            ->label('Serial Number')
                            ->reactive()
                            ->extraAttributes([
                                'wire:keydown.enter' => 'processSnoNo($event.target.value)',
                            ]),
                    ])
                    ->columns(4),
            ]);
    }

    public function processSnoNo($qrcode)
    {

        $parts = explode('|', $qrcode, 2);

        $itemCode = $parts[0] ?? null;
        $serialNumber = $parts[1] ?? null;

        $plantId = $this->form->getState()['plant_id'];

        $plantId = trim($plantId) ?? null;

        $workCenter = $this->form->getState()['machine_id'];

        $prodOrderNo= $this->form->getState()['production_order'];

        $prodOrderNo = trim($prodOrderNo) ?? null;


        if (!$qrcode || !preg_match('/^\d+\|\d+$/', $qrcode)) {
            Notification::make()
                ->title('Invalid QR Code')
                ->body('QR code format should be like: 123456|12456456464')
                ->danger()
                ->send();

            $this->form->fill([
                'plant_id' => $plantId,
                'machine_id' => $workCenter,
                'production_order' => $prodOrderNo,
                'serial_number' => null,
            ]);

            return;
        }
        elseif (!preg_match('/^[A-Za-z0-9]+$/', $itemCode)) {
            Notification::make()
                ->title('Invalid Item Code')
                ->body('Item code should contain only alpha-numeric values.')
                ->danger()
                ->send();

            $this->form->fill([
                'plant_id' => $plantId,
                'machine_id' => $workCenter,
                'production_order' => $prodOrderNo,
                'serial_number' => null,
            ]);

            return;
        }
        elseif (!preg_match('/^[A-Za-z0-9]+$/', $serialNumber)) {
            Notification::make()
                ->title('Invalid Serial Number')
                ->body('Serial number should contain only alpha-numeric values.')
                ->danger()
                ->send();

            $this->form->fill([
                'plant_id' => $plantId,
                'machine_id' => $workCenter,
                'production_order' => $prodOrderNo,
                'serial_number' => null,
            ]);

            return;
        }

        $plant = Plant::find($plantId);

        $plantName = $plant ? $plant->name : null;

        $pOrderExist = ProductionOrder::where('plant_id', $plantId)
            ->where('production_order', $prodOrderNo)
            ->first();

        if(!$pOrderExist){
            Notification::make()
                ->title('Unknown Production Order')
                ->body("Production Order not found against plant '$plantName'.")
                ->danger()
                ->send();

            $this->form->fill([
                'plant_id' => $plantId,
                'machine_id' => $workCenter,
                'production_order' => $prodOrderNo,
                'serial_number' => null,
            ]);

            return;
        }

        $itemExist = Item::where('code', $itemCode)->first();

        $itemAgaPlant = Item::where('code', $itemCode)->where('plant_id', $plantId)->first();

        if(!$itemExist){
            Notification::make()
                ->title('Unknown Item Code')
                ->body("Item code '$itemCode' not found.")
                ->danger()
                ->send();

            $this->form->fill([
                'plant_id' => $plantId,
                'machine_id' => $workCenter,
                'production_order' => $prodOrderNo,
                'serial_number' => null,
            ]);

            return;
        }
        elseif(!$itemAgaPlant){
            Notification::make()
                ->title('Unknown Item Code')
                ->body("Item code '$itemCode' not found against the the plant '$plantName'.")
                ->danger()
                ->send();

            $this->form->fill([
                'plant_id' => $plantId,
                'machine_id' => $workCenter,
                'production_order' => $prodOrderNo,
                'serial_number' => null,
            ]);

            return;
        }
        elseif ($itemAgaPlant->id != $pOrderExist->item_id) {
            Notification::make()
                ->title('Item Code Mismatch')
                ->body("Item code '$itemCode' does not match the item associated with production order '$prodOrderNo'.")
                ->danger()
                ->send();

            $this->form->fill([
                'plant_id' => $plantId,
                'machine_id' => $workCenter,
                'production_order' => $prodOrderNo,
                'serial_number' => null,
            ]);

            return;
        }

        $productionOrders = ProductionOrder::where('plant_id', $plantId)
            ->where('production_order', $prodOrderNo)
            ->where('item_id', $itemAgaPlant->id)
            ->get();

        $serialExist = null;

        foreach ($productionOrders as $productionOrder) {

            for (
                $serial = (int) $productionOrder->from_serial_number;
                $serial <= (int) $productionOrder->to_serial_number;
                $serial++
            ) {
                if ($serial == (int) $serialNumber) {
                    $serialExist = $productionOrder;
                    break 2;
                }
            }
        }

        if(!$serialExist){
            Notification::make()
                ->title('Serial Number Not Found')
                ->body("Serial number '$serialNumber' not found for production order '$prodOrderNo', item '$itemCode' and plant '$plantName'.")
                ->danger()
                ->send();

            $this->form->fill([
                'plant_id' => $plantId,
                'machine_id' => $workCenter,
                'production_order' => $prodOrderNo,
                'serial_number' => null,
            ]);

            return;
        }


        //..Generate Sticker PDF and download it

        $this->ref_number = $this->form->getState()['production_order'];

        $this->serNo = $serialNumber;

        $user = Filament::auth()->user();

        $operatorName = $user->name;

        $duplicate = StickerValidation::where('plant_id', $plantId)
            ->where('production_order', $this->ref_number)
            ->where('serial_number', $serialNumber)
            ->first();

        if ($duplicate) {
            Notification::make()
                ->danger()
                ->title('Duplicate Serial Number')
                ->body("Serial number $serialNumber already exists for this plant and production order!")
                ->seconds(3)
                ->send();

            $this->form->fill([
                'plant_id' => $plantId,
                'machine_id' => $workCenter,
                'production_order' => $this->ref_number,
                'serial_number' => null,
            ]);
            return;
        }

        $itemC = Item::where('code', $itemCode)
        ->where('plant_id',$plantId)
        ->first();

        $itemId = $itemC->id;

        $item = ItemCharacteristic::where('item_id', $itemId)
        ->where('plant_id',$plantId)
        ->first();

        $itemI = $item->id;

        $mapping = StickerMappingMaster::where('plant_id', $plantId)
            ->where('sticker1_machine_id', $workCenter)
            ->where('item_characteristic_id', $itemI)
            ->first();

        if (!$mapping) {
            Notification::make()
                ->danger()
                ->title('Sticker Mapping Not Found')
                ->body("No sticker mapping found for this item and plant.")
                ->send();
            return;
        }

        $stickers = [];

        for ($i = 1; $i <= 8; $i++) {
            $machineColumn = "sticker{$i}_machine_id";
            $ipColumn      = "sticker{$i}_print_ip";
            $stickerColumn = "sticker_structure{$i}_id";
            $itemColumn = "item_characteristic_id";

            if (
                !empty($mapping->$machineColumn) &&
                !empty($mapping->$stickerColumn)
            ) {
                $stickers[] = [
                    'machine_id' => $mapping->$machineColumn,
                    'sticker_id' => $mapping->$stickerColumn,
                    'item_characteristic'   => $mapping->$itemColumn,
                    'print_ip'   => $mapping->$ipColumn,
                ];
            }
        }

        if (empty($stickers)) {
            Notification::make()
                ->danger()
                ->title('No Sticker Configuration Found')
                ->body('No sticker and machine mappings configured for this item and plant.')
                ->send();
            return;
        }


        StickerValidation::create([
            'plant_id' => $plantId,
            'machine_id' => $workCenter,
            'production_order' => $this->ref_number ?? null,
            'serial_number' => $serialNumber,
            'status'  => 'Printed',
            // 'sticker_id' => $matchedSticker,
            'created_by' => $operatorName,
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        Notification::make()
            ->success()
            ->title('Sticker Recorded')
            ->body("Item: $itemCode, Serial: $serialNumber recorded successfully!")
            ->seconds(3)
            ->send();

        $this->form->fill([
            'plant_id' => $plantId,
            'machine_id' => $workCenter,
            'production_order' => $this->ref_number,
            'serial_number' => null,
        ]);

        $pdfUrls = [];

        foreach ($stickers as $sticker)
        {

            $structure = StickerStructureDetail::findOrFail($sticker['sticker_id']);

            $itemCharacteristic = ItemCharacteristic::where('plant_id', $plantId)
                ->where('id', $sticker['item_characteristic'])
                ->firstOrFail();

            $dynamicElements = StickerDetail::where(
                'sticker_structure_detail_id',
                $structure->id
            )->where('element_type', 'Dynamic')->get();

            $pdfContent = (new StickerPdfService())->generatePdf1(
                $structure->sticker_id,
                $dynamicElements,
                $itemCharacteristic,
                $serialNumber,
                $itemCode,
                $plantId
            );

            $tempPdfPath = storage_path('app/temp_sticker_' . uniqid() . '.pdf');

            file_put_contents($tempPdfPath, $pdfContent);

            // $pdfUrl = route('sticker.preview', [
            //     'path' => basename($tempPdfPath),
            // ]);
            $pdfUrls[] = route('sticker.preview', ['path' => basename($tempPdfPath)]);
        }

        $this->dispatch('open-sticker-pdf', urls: $pdfUrls);

        Notification::make()
            ->success()
            ->title('Sticker Printed')
            ->body("Sticker for Serial Number: $serialNumber printed successfully!")
            ->seconds(3)
            ->send();
    }

    public static function canAccess(): bool
    {
        return Auth::check() && Auth::user()->can('view sticker print page');
    }
}
