<?php

namespace App\Filament\Imports;

use App\Models\Item;
use App\Models\Line;
use App\Models\Plant;
use App\Models\ProcessOrder;
use App\Models\ProductCharacteristicsMaster;
use App\Models\User;
use Filament\Actions\Imports\Exceptions\RowImportFailedException;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
use Filament\Facades\Filament;
use Str;

class ProcessOrderImporter extends Importer
{
    protected static ?string $model = ProcessOrder::class;

    public static function getColumns(): array
    {
        return [
            ImportColumn::make('plant')
                ->requiredMapping()
                ->exampleHeader('PLANT CODE')
                ->example('1200')
                ->label('PLANT CODE')
                ->relationship(resolveUsing: 'code')
                ->rules(['required']),
            ImportColumn::make('line')
                ->exampleHeader('LINE NAME')
                ->example('Poly Wrapped Wire SFG')
                ->label('LINE NAME')
                ->relationship(resolveUsing: 'name'),
            ImportColumn::make('item')
                ->requiredMapping()
                ->exampleHeader('ITEM CODE')
                ->example('123456')
                ->label('ITEM CODE')
                ->relationship(resolveUsing: 'code')
                ->rules(['required']),
            ImportColumn::make('process_order')
                ->requiredMapping()
                ->exampleHeader('PROCESS ORDER')
                ->example('202601123456')
                ->label('PROCESS ORDER')
                ->rules(['required']),
            ImportColumn::make('order_quantity')
                ->requiredMapping()
                ->exampleHeader('ORDER QUANTITY')
                ->example('1000')
                ->label('ORDER QUANTITY')
                ->rules(['required']),
            ImportColumn::make('updated_order_quantity')
                ->exampleHeader('UPDATED ORDER QUANTITY')
                ->label('UPDATED ORDER QUANTITY'),
            ImportColumn::make('coil_number')
                ->exampleHeader('COIL NUMBER')
                // ->example('01')
                ->label('COIL NUMBER'),
            ImportColumn::make('received_quantity')
                ->exampleHeader('RECEIVED QUANTITY')
                // ->example('01')
                ->label('RECEIVED QUANTITY'),
            ImportColumn::make('sfg_number')
                ->exampleHeader('SFG NUMBER')
                // ->example('200000220613-72')
                ->label('SFG NUMBER'),
            ImportColumn::make('machine_name')
                ->exampleHeader('MACHINE NAME')
                // ->example('WMIWRM13 - 2-L2')
                ->label('MACHINE NAME'),
            ImportColumn::make('scrap_quantity')
                ->exampleHeader('SCRAP QUANTITY')
                // ->example('0')
                ->label('SCRAP QUANTITY'),
            ImportColumn::make('rework_status')
                ->exampleHeader('REWORK STATUS')
                // ->example('0')
                ->label('REWORK STATUS'),
            ImportColumn::make('created_at')
                ->exampleHeader('CREATED AT')
                // ->example('2026-02-20 13:00:00')
                ->label('CREATED AT'),
            ImportColumn::make('updated_at')
                ->exampleHeader('UPDATED AT')
                // ->example('2026-02-20 13:00:00')
                ->label('UPDATED AT'),
            ImportColumn::make('created_by')
                ->exampleHeader('CREATED BY')
                // ->example('RAW01234')
                ->label('CREATED BY'),
            ImportColumn::make('updated_by')
                ->exampleHeader('UPDATED BY')
                // ->example('RAW01234')
                ->label('UPDATED BY'),
        ];
    }

    public function resolveRecord(): ?ProcessOrder
    {
        $warnMsg = [];
        $plant = null;
        $plantCod = trim($this->data['plant']) ?? '';
        $plantId = null;
        $iCode = trim($this->data['item']) ?? '';
        $itemId = null;
        $lineNam = trim($this->data['line']) ?? '';
        $lineId = null;
        $processOrder = trim($this->data['process_order'] ?? '');
        $coilNo = trim($this->data['coil_number'] ?? '');
        $sfgNo = trim($this->data['sfg_number'] ?? '');
        $machineName = trim($this->data['machine_name'] ?? '');
        $orderQuan = trim($this->data['order_quantity'] ?? '');
        $updatedOrderQuan = trim($this->data['updated_order_quantity'] ?? '');
        $scrapQuan = trim($this->data['scrap_quantity'] ?? '');
        $reworkStatus = trim($this->data['rework_status'] ?? '');
        $recQuan = trim($this->data['received_quantity'] ?? '');
        $createdAt = trim($this->data['created_at'] ?? '');
        $createdBy = trim($this->data['created_by'] ?? '');
        $updatedAt = trim($this->data['updated_at'] ?? '');
        $updatedBy = trim($this->data['updated_by'] ?? '');
        // $user = Filament::auth()->user();
        // $operatorName = $user->name;

        if ($plantCod == null || $plantCod == '') {
            $warnMsg[] = "Plant code can't be empty!";
        } elseif (Str::length($plantCod) < 4 || ! is_numeric($plantCod) || ! preg_match('/^[1-9]\d{3,6}$/', $plantCod)) {
            $warnMsg[] = 'Invalid plant code found';
        }
        if ($iCode == null || $iCode == '') {
            $warnMsg[] = "Item code can't be empty!";
        } elseif (Str::length($iCode) < 6 || ! ctype_alnum($iCode)) {
            $warnMsg[] = 'Invalid item code found!';
        }
        if ($machineName != null && $machineName != '' && Str::length($machineName) > 18) {
            $warnMsg[] = 'Invalid machine name found!';
        }
        if ($processOrder == null || $processOrder == '') {
            $warnMsg[] = "Process order can't be empty!";
        } elseif ($processOrder && (Str::contains($processOrder, '.') || Str::contains($processOrder, 'E', ignoreCase: true))) {
            $warnMsg[] = 'Invalid process order found!';
        }
        if ($lineNam == null || $lineNam == '') {
            $warnMsg[] = "Line name can't be empty!";
        }
        if ($orderQuan == null || $orderQuan == '') {
            $warnMsg[] = "Order quantity can't be empty!";
        } elseif ($orderQuan == 0 || $orderQuan == '0') {
            $warnMsg[] = "Order quantity can't be zero!";
        } elseif (Str::length($orderQuan) >= 1 && ! is_numeric($orderQuan)) {
            $warnMsg[] = 'Invalid order quantity found!';
        }
        if ($updatedOrderQuan == null || $updatedOrderQuan == '' || $updatedOrderQuan == 0 || $updatedOrderQuan == '0') {
            $updatedOrderQuan = $orderQuan;
        } elseif (Str::length($updatedOrderQuan) >= 1 && ! is_numeric($updatedOrderQuan)) {
            $warnMsg[] = 'Invalid Updated order quantity found!';
        }

        if ($coilNo == null || $coilNo == '') {
            $coilNo = '0';
        }
        if ($scrapQuan == null || $scrapQuan == '') {
            $scrapQuan = 0;
        }
        if ($recQuan == null || $recQuan == '') {
            $recQuan = 0;
        }
        if ($reworkStatus == null || $reworkStatus = '' || $reworkStatus == 0 || $reworkStatus = '0') {
            $reworkStatus = 0;
        } elseif ($reworkStatus == 1 || $reworkStatus = '1') {
            $reworkStatus = 1;
        } else {
            $warnMsg[] = 'Invalid rework status found!';
        }

        if (! empty($warnMsg)) {
            throw new RowImportFailedException(implode(', ', $warnMsg));
        }

        $plant = Plant::where('code', $plantCod)->first();
        if (! $plant) {
            $warnMsg[] = 'Plant not found!';
        } else {
            $plantId = $plant->id;
        }

        // TESTING PURPOSE ONLY - TO CHECK DUPLICATE PROCESS ORDER WITH SAME COIL NUMBER FOR THE SAME PLANT
        // $existing = ProcessOrder::where('plant_id', $plantId)->where('process_order', $processOrder)->first();
        // if ($existing) {
        //     $existing = ProcessOrder::where('plant_id', $plantId)->where('process_order', $processOrder)->where('coil_number', $coilNo)->first();
        //     if ($existing) {
        //         $warnMsg[] = 'Process Order with coil number already exists!';
        //     } else {
        //     $warnMsg[] = 'Process order already exists!';
        //     }
        // } else {
        //     $warnMsg[] = 'New process order found!';
        // }
        // if (! empty($warnMsg)) {
        //     throw new RowImportFailedException(implode(', ', $warnMsg));
        // }

        $itemCode = Item::where('code', $iCode)->first();
        if (! $itemCode) {
            $warnMsg[] = 'Item code not found!';
        } else {
            if ($plantId) {
                $itemCode = Item::where('code', $iCode)->where('plant_id', $plantId)->first();
                if (! $itemCode) {
                    $warnMsg[] = 'Item code not found for the given plant!';
                } else {
                    $itemId = $itemCode->id;
                }
            }
        }

        $lineExists = Line::where('name', $lineNam)->first();
        if (! $lineExists) {
            $warnMsg[] = 'Line name not found!';
        } else {
            if ($plantId) {
                $lineAgainstPlant = Line::where('name', $lineNam)->where('plant_id', $plantId)->first();
                if (! $lineAgainstPlant) {
                    $warnMsg[] = 'Line name not found for the given plant!';
                } else {
                    $lineId = $lineAgainstPlant->id;
                }
            }
        }

        if ($plantId && $itemId && $lineId && $processOrder != '') {
            $existingOrder = ProcessOrder::where('plant_id', $plantId)
                ->where('process_order', $processOrder)
                ->first();

            if ($existingOrder && $existingOrder->item_id !== ($itemId ?? null)) {
                $warnMsg[] = 'Same Process Order already exists for this Plant with a different Item Code!';
            }

            // $masterExist = ProductCharacteristicsMaster::where('plant_id', $plantId)->where('item_id', $itemId)->first();

            // if (! $masterExist) {
            //     $warnMsg[] = 'Characteristics master not found for the given plant!';
            // } else {
            //     $masterExist = ProductCharacteristicsMaster::where('plant_id', $plantId)->where('line_id', $lineId)->where('item_id', $itemId)->first();

            //     if (! $masterExist) {
            //         $warnMsg[] = 'Characteristics master not found for the given line!';
            //     }
            // }
        }

        // $user = User::where('name', $this->data['created_by'])->first();
        // if (! $user) {
        //     $warnMsg[] = 'User not found!';
        // }

        if (! $createdBy) {
            $createdBy = Filament::auth()->user()->name;
            $updatedBy = Filament::auth()->user()->name;
        } elseif (! $updatedBy) {
            $updatedBy = Filament::auth()->user()->name;
        }

        if (! empty($warnMsg)) {
            throw new RowImportFailedException(implode(', ', $warnMsg));
        }

        $existing = ProcessOrder::where('plant_id', $plantId)
            ->where('process_order', $processOrder)
            // ->where('coil_number', $coilNo)
            ->first();

        $receivedQty = ProcessOrder::where('plant_id', $plantId)
            ->where('process_order', $processOrder)
            ->sum('received_quantity');

        if ($existing) {
            $liveOrdQuan = (float) $existing->order_quantity;
            $liveUpdatedOrdQuan = (float) $existing->updated_order_quantity;

            $allowedIncrease = $liveOrdQuan * 0.10;

            $maxAllowedQty = $liveOrdQuan + $allowedIncrease;
            $minAllowedQty = $liveOrdQuan - $allowedIncrease;

            if ($liveUpdatedOrdQuan > $maxAllowedQty) {
                throw new RowImportFailedException(
                    "Updated order quantity cannot exceed 10% of existing order quantity. Max allowed: {$maxAllowedQty}!"
                );
            } elseif ($liveUpdatedOrdQuan < $minAllowedQty) {
                throw new RowImportFailedException(
                    "Updated order quantity cannot decrease -10% of existing order quantity. Min allowed: {$minAllowedQty}!"
                );
            } elseif ($liveUpdatedOrdQuan < $receivedQty) {
                throw new RowImportFailedException(
                    "Updated order quantity cannot decrease below its received quantity {$receivedQty}!"
                );
            }
        }

        if ($coilNo != null && $coilNo != '' && $scrapQuan && $reworkStatus && $recQuan && $createdAt && $createdBy && $updatedAt && $updatedBy && Filament::auth()->user()->hasRole('Super Admin')) {
            $existingCoil = ProcessOrder::where('plant_id', $plantId)
                ->where('process_order', $processOrder)
                ->where('line_id', $lineId)
                ->where('coil_number', $coilNo)
                ->first();

            // $existingProcess = ProcessOrder::where('plant_id', $plantId)
            //     ->where('process_order', $processOrder)
            //     ->where('line_id', $lineId)
            //     ->first();

            if ($existing) {
                $existUpdateOrdQuan = $existing->updated_order_quantity;
            } else {
                $existUpdateOrdQuan = $updatedOrderQuan;
            }

            if (! $existingCoil) {
                ProcessOrder::Create(
                    [
                        'plant_id' => $plantId,
                        'line_id' => $lineId,
                        'process_order' => $processOrder,
                        'item_id' => $itemId,
                        'coil_number' => $coilNo,
                        'order_quantity' => $orderQuan,
                        'updated_order_quantity' => $existUpdateOrdQuan,
                        'received_quantity' => $recQuan,
                        'scrap_quantity' => $scrapQuan,
                        'sfg_number' => $sfgNo,
                        'machine_name' => $machineName,
                        'rework_status' => $reworkStatus,
                        'created_at' => $createdAt,
                        'updated_at' => $updatedAt,
                        'created_by' => $createdBy,
                        'updated_by' => $updatedBy,
                    ]
                );
            } else {
                ProcessOrder::where('plant_id', $plantId)
                    ->where('process_order', $processOrder)
                    ->where('line_id', $lineId)
                    ->where('coil_number', $coilNo)
                    ->update([
                        // 'order_quantity'    => $orderQty,
                        'received_quantity' => $recQuan,
                        'scrap_quantity' => $scrapQuan,
                        // 'sfg_number'        => $sfgNo,
                        // 'machine_name'      => $machineId,
                        'rework_status' => $reworkStatus,
                        'updated_by' => $updatedBy,
                        'updated_at' => $updatedAt,
                    ]);
            }
        } else {
            $coilNo = '0';
            // $existing = ProcessOrder::where('plant_id', $plantId)
            //     ->where('process_order', $processOrder)
            //     // ->where('coil_number', $coilNo)
            //     ->first();

            if ($existing) {
                $existUpdateOrdQuan = $existing->updated_order_quantity;
            } else {
                $existUpdateOrdQuan = $updatedOrderQuan;
            }

            if (! $existing && ($coilNo == '0' || $coilNo == 0)) {
                ProcessOrder::create([
                    'plant_id' => $plantId,
                    'line_id' => $lineId,
                    'item_id' => $itemId,
                    'process_order' => $processOrder,
                    'coil_number' => '0',
                    'order_quantity' => $orderQuan,
                    'updated_order_quantity' => $existUpdateOrdQuan,
                    'received_quantity' => 0,
                    'scrap_quantity' => 0,
                    'created_by' => $createdBy,
                    'updated_by' => $updatedBy,
                ]);
            } elseif (! $existing) {
                ProcessOrder::Create(
                    [
                        'plant_id' => $plantId,
                        'line_id' => $lineId,
                        'item_id' => $itemId,
                        'process_order' => $processOrder,
                        'coil_number' => $coilNo,
                        'order_quantity' => $orderQuan,
                        'updated_order_quantity' => $existUpdateOrdQuan,
                        'received_quantity' => $recQuan,
                        'scrap_quantity' => $scrapQuan ?? 0,
                        'sfg_number' => $sfgNo,
                        'machine_name' => $machineName,
                        'rework_status' => $reworkStatus,
                        // 'created_at' => $createdAt,
                        // 'updated_at' => $updatedAt,
                        'created_by' => $createdBy,
                        'updated_by' => $updatedBy,
                    ]
                );
            } else {// $coilNo = '0'
                if ($existing->process_order == $processOrder) {
                    throw new RowImportFailedException('Process order already exist for the given plant!');
                } elseif ($existing->rework_status == 1 && $reworkStatus == 0) {
                    throw new RowImportFailedException('Rework coil number already exist for the given Plant and Process Order!');
                } else {
                    ProcessOrder::where('plant_id', $plantId)
                        ->where('process_order', $processOrder)
                        ->where('coil_number', $coilNo)
                        ->update([
                            // 'order_quantity'    => $orderQty,
                            'received_quantity' => $recQuan,
                            'scrap_quantity' => $scrapQuan,
                            // 'sfg_number'        => $sfgNo,
                            // 'machine_name'      => $machineId,
                            'rework_status' => $reworkStatus,
                            'updated_by' => $updatedBy,
                            // 'updated_at' => $updatedAt,
                        ]);
                }
            }
        }

        return null;

        // return new ProcessOrder();
    }

    public static function getCompletedNotificationBody(Import $import): string
    {
        $body = 'Your process order import has completed and '.number_format($import->successful_rows).' '.str('row')->plural($import->successful_rows).' imported.';

        if ($failedRowsCount = $import->getFailedRowsCount()) {
            $body .= ' '.number_format($failedRowsCount).' '.str('row')->plural($failedRowsCount).' failed to import.';
        }

        return $body;
    }
}
