<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Barcode extends Model
{
    use HasFactory;

    protected $fillable = [
        'item_id',
        'barcode_value',
        'barcode_type',
        'printed',
        'generated_by',
        'generated_at',
        'printed_at',
        'extra_data',
    ];

    protected $casts = [
        'item_id' => 'integer',
        'printed' => 'boolean',
        'generated_by' => 'integer',
        'generated_at' => 'datetime',
        'printed_at' => 'datetime',
        'extra_data' => 'array',
    ];

    /**
     * Get the item
     */
    public function item(): BelongsTo
    {
        return $this->belongsTo(Item::class);
    }

    /**
     * Get the user who generated this barcode
     */
    public function generatedBy(): BelongsTo
    {
        return $this->belongsTo(User::class, 'generated_by');
    }

    /**
     * Generate unique barcode value
     * Format depends on level:
     * - Department: رمز الفرع + رمز القسم + رقم الجهاز
     * - Section: رمز الفرع + رمز القسم + رمز الشعبة + رقم الجهاز
     * - Unit: رمز الفرع + رمز القسم + رمز الشعبة + رمز الوحدة + رقم الجهاز
     */
    public static function generateValue(Item $item, int $sequence = 1, ?string $level = null): string
    {
        $orgCode = $item->organization->code ?? 'ORG';
        $deptCode = $item->department ? $item->department->code : 'DEPT';
        
        // تحديد المستوى تلقائياً إذا لم يتم تحديده
        if (!$level) {
            if ($item->unit && $item->unit->code) {
                $level = 'unit';
            } elseif ($item->section && $item->section->code) {
                $level = 'section';
            } else {
                $level = 'department';
            }
        }
        
        // بناء الترميز حسب المستوى
        switch ($level) {
            case 'unit':
                // للوحدة: رمز الفرع + رمز القسم + رمز الشعبة + رمز الوحدة + رقم الجهاز
                $sectionCode = $item->section ? $item->section->code : ($item->unit && $item->unit->section ? $item->unit->section->code : 'SEC');
                $unitCode = $item->unit ? $item->unit->code : 'UNIT';
                $value = sprintf(
                    '%s-%s-%s-%s-%s',
                    $orgCode,
                    $deptCode,
                    $sectionCode,
                    $unitCode,
                    str_pad($sequence, 3, '0', STR_PAD_LEFT)
                );
                break;
                
            case 'section':
                // للشعبة: رمز الفرع + رمز القسم + رمز الشعبة + رقم الجهاز
                $sectionCode = $item->section ? $item->section->code : ($item->unit && $item->unit->section ? $item->unit->section->code : 'SEC');
                $value = sprintf(
                    '%s-%s-%s-%s',
                    $orgCode,
                    $deptCode,
                    $sectionCode,
                    str_pad($sequence, 3, '0', STR_PAD_LEFT)
                );
                break;
                
            case 'department':
            default:
                // للقسم: رمز الفرع + رمز القسم + رقم الجهاز
                $value = sprintf(
                    '%s-%s-%s',
                    $orgCode,
                    $deptCode,
                    str_pad($sequence, 3, '0', STR_PAD_LEFT)
                );
                break;
        }

        // Ensure uniqueness
        while (static::where('barcode_value', $value)->exists()) {
            $sequence++;
            switch ($level) {
                case 'unit':
                    $sectionCode = $item->section ? $item->section->code : ($item->unit && $item->unit->section ? $item->unit->section->code : 'SEC');
                    $unitCode = $item->unit ? $item->unit->code : 'UNIT';
                    $value = sprintf(
                        '%s-%s-%s-%s-%s',
                        $orgCode,
                        $deptCode,
                        $sectionCode,
                        $unitCode,
                        str_pad($sequence, 3, '0', STR_PAD_LEFT)
                    );
                    break;
                case 'section':
                    $sectionCode = $item->section ? $item->section->code : ($item->unit && $item->unit->section ? $item->unit->section->code : 'SEC');
                    $value = sprintf(
                        '%s-%s-%s-%s',
                        $orgCode,
                        $deptCode,
                        $sectionCode,
                        str_pad($sequence, 3, '0', STR_PAD_LEFT)
                    );
                    break;
                case 'department':
                default:
                    $value = sprintf(
                        '%s-%s-%s',
                        $orgCode,
                        $deptCode,
                        str_pad($sequence, 3, '0', STR_PAD_LEFT)
                    );
                    break;
            }
        }

        return $value;
    }

    /**
     * Mark as printed
     */
    public function markAsPrinted(): void
    {
        $this->update([
            'printed' => true,
            'printed_at' => now(),
        ]);
    }

    /**
     * Generate barcodes for all items in a department
     * ترقيم تلقائي للأجهزة في نفس القسم (001, 002, 003...)
     */
    public static function generateForDepartment(Department $department, string $barcodeType = 'code128'): array
    {
        $items = Item::with(['organization', 'department', 'section', 'unit.section', 'type'])
            ->where('department_id', $department->id)
            ->get();

        if ($items->isEmpty()) {
            return [];
        }

        $barcodes = [];
        $userId = auth()->id();
        
        // الحصول على آخر تسلسل في هذا القسم
        $orgCode = $department->organization->code ?? 'ORG';
        $deptCode = $department->code ?? 'DEPT';
        $lastBarcode = static::where('barcode_value', 'like', $orgCode . '-' . $deptCode . '-%')
            ->orderBy('barcode_value', 'desc')
            ->first();
        
        $globalSequence = 1;
        if ($lastBarcode) {
            // استخراج آخر تسلسل من الباركود
            $parts = explode('-', $lastBarcode->barcode_value);
            if (count($parts) >= 3) {
                $lastSeq = (int) end($parts);
                $globalSequence = $lastSeq + 1;
            }
        }

        foreach ($items as $item) {
            $quantity = max((int) ($item->quantity ?? 1), 1);

            // لكل جهاز في نفس المادة، رقم تسلسلي مختلف
            for ($i = 1; $i <= $quantity; $i++) {
                $barcodeValue = static::generateValue($item, $globalSequence, 'department');

                $barcodes[] = static::create([
                    'item_id' => $item->id,
                    'barcode_value' => $barcodeValue,
                    'barcode_type' => $barcodeType,
                    'generated_by' => $userId,
                    'generated_at' => now(),
                    'extra_data' => [
                        'organization' => optional($item->organization)->name ?? 'غير محدد',
                        'department' => optional($item->department)->name ?? 'غير محدد',
                        'section' => optional($item->section)->name ?? optional(optional($item->unit)->section)->name ?? 'غير محدد',
                        'unit' => optional($item->unit)->name ?? 'غير محدد',
                        'type' => optional($item->type)->name ?? 'غير محدد',
                        'item_name' => $item->name,
                        'sequence' => $globalSequence, // تسلسل فريد لكل جهاز
                        'level' => 'department', // تحديد المستوى
                        'bulk_generated' => true,
                    ],
                ]);
                
                $globalSequence++; // زيادة التسلسل لكل جهاز
            }
        }

        return $barcodes;
    }

    /**
     * Generate barcodes for all items in a section
     * ترقيم تلقائي للأجهزة في نفس الشعبة (001, 002, 003...)
     */
    public static function generateForSection(Section $section, string $barcodeType = 'code128'): array
    {
        $items = Item::with(['organization', 'department', 'section', 'unit.section', 'type'])
            ->where('section_id', $section->id)
            ->get();

        if ($items->isEmpty()) {
            return [];
        }

        $barcodes = [];
        $userId = auth()->id();
        
        // الحصول على آخر تسلسل في هذه الشعبة
        $orgCode = $section->department->organization->code ?? 'ORG';
        $deptCode = $section->department->code ?? 'DEPT';
        $sectionCode = $section->code ?? 'SEC';
        $lastBarcode = static::where('barcode_value', 'like', $orgCode . '-' . $deptCode . '-' . $sectionCode . '-%')
            ->orderBy('barcode_value', 'desc')
            ->first();
        
        $globalSequence = 1;
        if ($lastBarcode) {
            // استخراج آخر تسلسل من الباركود
            $parts = explode('-', $lastBarcode->barcode_value);
            if (count($parts) >= 4) {
                $lastSeq = (int) end($parts);
                $globalSequence = $lastSeq + 1;
            }
        }

        foreach ($items as $item) {
            $quantity = max((int) ($item->quantity ?? 1), 1);

            // لكل جهاز في نفس المادة، رقم تسلسلي مختلف
            for ($i = 1; $i <= $quantity; $i++) {
                $barcodeValue = static::generateValue($item, $globalSequence, 'section');

                $barcodes[] = static::create([
                    'item_id' => $item->id,
                    'barcode_value' => $barcodeValue,
                    'barcode_type' => $barcodeType,
                    'generated_by' => $userId,
                    'generated_at' => now(),
                    'extra_data' => [
                        'organization' => optional($item->organization)->name ?? 'غير محدد',
                        'department' => optional($item->department)->name ?? 'غير محدد',
                        'section' => optional($item->section)->name ?? optional(optional($item->unit)->section)->name ?? 'غير محدد',
                        'unit' => optional($item->unit)->name ?? 'غير محدد',
                        'type' => optional($item->type)->name ?? 'غير محدد',
                        'item_name' => $item->name,
                        'sequence' => $globalSequence, // تسلسل فريد لكل جهاز
                        'level' => 'section', // تحديد المستوى
                        'bulk_generated' => true,
                    ],
                ]);
                
                $globalSequence++; // زيادة التسلسل لكل جهاز
            }
        }

        return $barcodes;
    }

    /**
     * Generate barcodes for all items in a unit
     * ترقيم تلقائي للأجهزة في نفس الوحدة (001, 002, 003...)
     */
    public static function generateForUnit(Unit $unit, string $barcodeType = 'code128'): array
    {
        $items = Item::with(['organization', 'department', 'section', 'unit.section', 'type'])
            ->where('unit_id', $unit->id)
            ->get();

        if ($items->isEmpty()) {
            return [];
        }

        $barcodes = [];
        $userId = auth()->id();
        
        // الحصول على آخر تسلسل في هذه الوحدة
        $orgCode = $unit->organization->code ?? 'ORG';
        $deptCode = $unit->department->code ?? 'DEPT';
        $sectionCode = $unit->section ? $unit->section->code : 'SEC';
        $unitCode = $unit->code ?? 'UNIT';
        $lastBarcode = static::where('barcode_value', 'like', $orgCode . '-' . $deptCode . '-' . $sectionCode . '-' . $unitCode . '-%')
            ->orderBy('barcode_value', 'desc')
            ->first();
        
        $globalSequence = 1;
        if ($lastBarcode) {
            // استخراج آخر تسلسل من الباركود
            $parts = explode('-', $lastBarcode->barcode_value);
            if (count($parts) >= 5) {
                $lastSeq = (int) end($parts);
                $globalSequence = $lastSeq + 1;
            }
        }

        foreach ($items as $item) {
            $quantity = max((int) ($item->quantity ?? 1), 1);

            // لكل جهاز في نفس المادة، رقم تسلسلي مختلف
            for ($i = 1; $i <= $quantity; $i++) {
                $barcodeValue = static::generateValue($item, $globalSequence, 'unit');

                $barcodes[] = static::create([
                    'item_id' => $item->id,
                    'barcode_value' => $barcodeValue,
                    'barcode_type' => $barcodeType,
                    'generated_by' => $userId,
                    'generated_at' => now(),
                    'extra_data' => [
                        'organization' => optional($item->organization)->name ?? 'غير محدد',
                        'department' => optional($item->department)->name ?? 'غير محدد',
                        'section' => optional($item->section)->name ?? optional(optional($item->unit)->section)->name ?? 'غير محدد',
                        'unit' => optional($item->unit)->name ?? 'غير محدد',
                        'type' => optional($item->type)->name ?? 'غير محدد',
                        'item_name' => $item->name,
                        'sequence' => $globalSequence, // تسلسل فريد لكل جهاز
                        'level' => 'unit', // تحديد المستوى
                        'bulk_generated' => true,
                    ],
                ]);
                
                $globalSequence++; // زيادة التسلسل لكل جهاز
            }
        }

        return $barcodes;
    }
}

