<?php

namespace App\Http\Controllers;

use App\Models\InventoryItem;
use App\Models\InventorySerial;
use App\Models\Warehouse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class InventorySerialController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $companyId = auth()->user()->company_id;

        $serials = InventorySerial::whereHas('item', function ($query) use ($companyId) {
            $query->where('company_id', $companyId);
        })
            ->with(['item', 'warehouse'])
            ->orderBy('created_at', 'desc')
            ->paginate(15);

        return view('inventory.serials.index', compact('serials'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $companyId = auth()->user()->company_id;
        $items = InventoryItem::where('company_id', $companyId)
            ->where('track_serials', true)
            ->orderBy('name')
            ->get();
        $warehouses = Warehouse::where('company_id', $companyId)
            ->orderBy('name')
            ->get();

        return view('inventory.serials.create', compact('items', 'warehouses'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request->validate([
            'item_id' => 'required|exists:inventory_items,id',
            'warehouse_id' => 'required|exists:warehouses,id',
            'serial_numbers' => 'required|string',
            'purchase_date' => 'nullable|date',
            'warranty_expiry' => 'nullable|date|after_or_equal:purchase_date',
            'notes' => 'nullable|string',
        ]);

        // التحقق من أن العنصر والمستودع ينتميان للشركة الحالية
        $item = InventoryItem::findOrFail($request->item_id);
        $warehouse = Warehouse::findOrFail($request->warehouse_id);

        if ($item->company_id != auth()->user()->company_id || $warehouse->company_id != auth()->user()->company_id) {
            return redirect()->back()->with('error', 'لا يمكنك إضافة أرقام تسلسلية لعنصر أو مستودع لا ينتمي لشركتك');
        }

        // التحقق من أن العنصر يتتبع الأرقام التسلسلية
        if (!$item->track_serials) {
            return redirect()->back()->with('error', 'هذا العنصر لا يتتبع الأرقام التسلسلية');
        }

        // تقسيم الأرقام التسلسلية إلى مصفوفة
        $serialNumbers = preg_split('/\r\n|\r|\n|,/', $request->serial_numbers);
        $serialNumbers = array_map('trim', $serialNumbers);
        $serialNumbers = array_filter($serialNumbers);

        if (empty($serialNumbers)) {
            return redirect()->back()->with('error', 'يرجى إدخال رقم تسلسلي واحد على الأقل');
        }

        // التحقق من عدم وجود أرقام تسلسلية مكررة
        $existingSerials = InventorySerial::where('item_id', $request->item_id)
            ->whereIn('serial_number', $serialNumbers)
            ->pluck('serial_number')
            ->toArray();

        if (!empty($existingSerials)) {
            return redirect()->back()->with('error', 'الأرقام التسلسلية التالية موجودة بالفعل: ' . implode(', ', $existingSerials));
        }

        DB::beginTransaction();

        try {
            $createdSerials = [];

            foreach ($serialNumbers as $serialNumber) {
                // إنشاء رقم تسلسلي جديد
                $serial = new InventorySerial();
                $serial->item_id = $request->item_id;
                $serial->warehouse_id = $request->warehouse_id;
                $serial->serial_number = $serialNumber;
                $serial->status = 'in_stock';
                $serial->purchase_date = $request->purchase_date;
                $serial->warranty_expiry = $request->warranty_expiry;
                $serial->notes = $request->notes;
                $serial->created_by = Auth::id();
                $serial->save();

                $createdSerials[] = $serial;

                // إنشاء حركة مخزون
                $this->createInventoryTransaction($item->id, $warehouse->id, 1, 'serial_added', null, $serial->id);
            }

            // تحديث مخزون العنصر في المستودع
            $this->updateItemStock($item->id, $warehouse->id, count($serialNumbers));

            DB::commit();

            return redirect()->route('inventory-serials.index')
                ->with('success', 'تم إضافة ' . count($createdSerials) . ' رقم تسلسلي بنجاح');
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()->with('error', 'حدث خطأ أثناء إضافة الأرقام التسلسلية: ' . $e->getMessage());
        }
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\InventorySerial  $inventorySerial
     * @return \Illuminate\Http\Response
     */
    public function show(InventorySerial $inventorySerial)
    {
        // التحقق من أن الرقم التسلسلي ينتمي للشركة الحالية
        if ($inventorySerial->item->company_id != auth()->user()->company_id) {
            return redirect()->route('inventory-serials.index')
                ->with('error', 'لا يمكنك عرض رقم تسلسلي لا ينتمي لشركتك');
        }

        $inventorySerial->load(['item', 'warehouse', 'createdBy']);

        // الحصول على حركات المخزون المرتبطة بهذا الرقم التسلسلي
        $transactions = \App\Models\InventoryTransaction::where('serial_id', $inventorySerial->id)
            ->with(['createdBy'])
            ->orderBy('created_at', 'desc')
            ->get();

        return view('inventory.serials.show', compact('inventorySerial', 'transactions'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\InventorySerial  $inventorySerial
     * @return \Illuminate\Http\Response
     */
    public function edit(InventorySerial $inventorySerial)
    {
        // التحقق من أن الرقم التسلسلي ينتمي للشركة الحالية
        if ($inventorySerial->item->company_id != auth()->user()->company_id) {
            return redirect()->route('inventory-serials.index')
                ->with('error', 'لا يمكنك تعديل رقم تسلسلي لا ينتمي لشركتك');
        }

        return view('inventory.serials.edit', compact('inventorySerial'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\InventorySerial  $inventorySerial
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, InventorySerial $inventorySerial)
    {
        // التحقق من أن الرقم التسلسلي ينتمي للشركة الحالية
        if ($inventorySerial->item->company_id != auth()->user()->company_id) {
            return redirect()->route('inventory-serials.index')
                ->with('error', 'لا يمكنك تعديل رقم تسلسلي لا ينتمي لشركتك');
        }

        $request->validate([
            'serial_number' => 'required|string|max:255',
            'purchase_date' => 'nullable|date',
            'warranty_expiry' => 'nullable|date|after_or_equal:purchase_date',
            'notes' => 'nullable|string',
        ]);

        // التحقق من عدم وجود رقم تسلسلي آخر بنفس الرقم لنفس العنصر
        $existingSerial = InventorySerial::where('item_id', $inventorySerial->item_id)
            ->where('serial_number', $request->serial_number)
            ->where('id', '!=', $inventorySerial->id)
            ->exists();

        if ($existingSerial) {
            return redirect()->back()->with('error', 'يوجد رقم تسلسلي آخر بنفس الرقم لهذا العنصر');
        }

        $inventorySerial->serial_number = $request->serial_number;
        $inventorySerial->purchase_date = $request->purchase_date;
        $inventorySerial->warranty_expiry = $request->warranty_expiry;
        $inventorySerial->notes = $request->notes;
        $inventorySerial->save();

        return redirect()->route('inventory-serials.index')
            ->with('success', 'تم تحديث الرقم التسلسلي بنجاح');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\InventorySerial  $inventorySerial
     * @return \Illuminate\Http\Response
     */
    public function destroy(InventorySerial $inventorySerial)
    {
        // التحقق من أن الرقم التسلسلي ينتمي للشركة الحالية
        if ($inventorySerial->item->company_id != auth()->user()->company_id) {
            return redirect()->route('inventory-serials.index')
                ->with('error', 'لا يمكنك حذف رقم تسلسلي لا ينتمي لشركتك');
        }

        // التحقق من أن الرقم التسلسلي في المخزن وليس مستخدمًا
        if ($inventorySerial->status != 'in_stock') {
            return redirect()->route('inventory-serials.index')
                ->with('error', 'لا يمكن حذف رقم تسلسلي مستخدم أو مباع');
        }

        DB::beginTransaction();

        try {
            // تحديث مخزون العنصر في المستودع
            $this->updateItemStock($inventorySerial->item_id, $inventorySerial->warehouse_id, -1);

            // حذف حركات المخزون المرتبطة بهذا الرقم التسلسلي
            \App\Models\InventoryTransaction::where('serial_id', $inventorySerial->id)->delete();

            // حذف الرقم التسلسلي
            $inventorySerial->delete();

            DB::commit();

            return redirect()->route('inventory-serials.index')
                ->with('success', 'تم حذف الرقم التسلسلي بنجاح');
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()->with('error', 'حدث خطأ أثناء حذف الرقم التسلسلي: ' . $e->getMessage());
        }
    }

    /**
     * تحديث كمية العنصر في المستودع
     *
     * @param  int  $itemId
     * @param  int  $warehouseId
     * @param  float  $quantity
     * @return void
     */
    private function updateItemStock($itemId, $warehouseId, $quantity)
    {
        $stock = \App\Models\InventoryStock::firstOrNew([
            'item_id' => $itemId,
            'warehouse_id' => $warehouseId,
        ]);

        if (!$stock->exists) {
            $stock->quantity = 0;
        }

        $stock->quantity += $quantity;
        $stock->save();
    }

    /**
     * إنشاء حركة مخزون
     *
     * @param  int  $itemId
     * @param  int  $warehouseId
     * @param  float  $quantity
     * @param  string  $transactionType
     * @param  int|null  $batchId
     * @param  int|null  $serialId
     * @return \App\Models\InventoryTransaction
     */
    private function createInventoryTransaction($itemId, $warehouseId, $quantity, $transactionType, $batchId = null, $serialId = null)
    {
        $transaction = new \App\Models\InventoryTransaction();
        $transaction->item_id = $itemId;
        $transaction->warehouse_id = $warehouseId;
        $transaction->quantity = $quantity;
        $transaction->transaction_type = $transactionType;
        $transaction->batch_id = $batchId;
        $transaction->serial_id = $serialId;
        $transaction->created_by = Auth::id();
        $transaction->save();

        return $transaction;
    }

    /**
     * تغيير حالة الرقم التسلسلي
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\InventorySerial  $inventorySerial
     * @return \Illuminate\Http\Response
     */
    public function changeStatus(Request $request, InventorySerial $inventorySerial)
    {
        // التحقق من أن الرقم التسلسلي ينتمي للشركة الحالية
        if ($inventorySerial->item->company_id != auth()->user()->company_id) {
            return redirect()->route('inventory-serials.index')
                ->with('error', 'لا يمكنك تعديل رقم تسلسلي لا ينتمي لشركتك');
        }

        $request->validate([
            'status' => 'required|in:in_stock,sold,defective,in_repair,reserved',
            'notes' => 'nullable|string',
        ]);

        $oldStatus = $inventorySerial->status;
        $newStatus = $request->status;

        if ($oldStatus == $newStatus) {
            return redirect()->back()->with('info', 'لم يتم تغيير الحالة');
        }

        DB::beginTransaction();

        try {
            // تحديث حالة الرقم التسلسلي
            $inventorySerial->status = $newStatus;
            $inventorySerial->save();

            // إنشاء حركة مخزون إذا كان التغيير من/إلى المخزن
            if ($oldStatus == 'in_stock' && $newStatus != 'in_stock') {
                // خروج من المخزن
                $this->updateItemStock($inventorySerial->item_id, $inventorySerial->warehouse_id, -1);
                $this->createInventoryTransaction(
                    $inventorySerial->item_id,
                    $inventorySerial->warehouse_id,
                    1,
                    'serial_status_changed',
                    null,
                    $inventorySerial->id
                );
            } elseif ($oldStatus != 'in_stock' && $newStatus == 'in_stock') {
                // عودة إلى المخزن
                $this->updateItemStock($inventorySerial->item_id, $inventorySerial->warehouse_id, 1);
                $this->createInventoryTransaction(
                    $inventorySerial->item_id,
                    $inventorySerial->warehouse_id,
                    1,
                    'serial_status_changed',
                    null,
                    $inventorySerial->id
                );
            }

            // إضافة ملاحظة لتغيير الحالة
            if ($request->filled('notes')) {
                $statusChangeNote = "تغيير الحالة من {$oldStatus} إلى {$newStatus}: {$request->notes}";
                $inventorySerial->notes = $inventorySerial->notes ? $inventorySerial->notes . "\n" . $statusChangeNote : $statusChangeNote;
                $inventorySerial->save();
            }

            DB::commit();

            return redirect()->route('inventory-serials.show', $inventorySerial)
                ->with('success', 'تم تغيير حالة الرقم التسلسلي بنجاح');
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()->with('error', 'حدث خطأ أثناء تغيير حالة الرقم التسلسلي: ' . $e->getMessage());
        }
    }

    /**
     * البحث عن رقم تسلسلي
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function search(Request $request)
    {
        $request->validate([
            'search' => 'required|string|min:3',
        ]);

        $companyId = auth()->user()->company_id;
        $search = $request->search;

        $serials = InventorySerial::whereHas('item', function ($query) use ($companyId) {
            $query->where('company_id', $companyId);
        })
            ->where(function ($query) use ($search) {
                $query->where('serial_number', 'like', "%{$search}%")
                    ->orWhereHas('item', function ($q) use ($search) {
                        $q->where('name', 'like', "%{$search}%")
                            ->orWhere('sku', 'like', "%{$search}%");
                    });
            })
            ->with(['item', 'warehouse'])
            ->orderBy('created_at', 'desc')
            ->paginate(15);

        return view('inventory.serials.index', compact('serials', 'search'));
    }
}
