<?php

namespace App\Http\Controllers\SuperAdmin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Grn;
use App\Models\GrnProductDetail;
use App\Models\CustomerVendor;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Models\SkuMaster;

class SuperAdminGRNController extends Controller
{
    // Show create GRN form
    public function grnPage()
    {
        $lastGRN = Grn::orderBy('id', 'desc')->first();
        $nextNumber = $lastGRN ? ((int)explode('/', $lastGRN->grn_no)[2]) + 1 : 1;
        $grnNo = 'UEPL/GRN/' . str_pad($nextNumber, 4, '0', STR_PAD_LEFT);

        $companies = CustomerVendor::all();
        $items = SkuMaster::all();
        return view('superadmin.grn.grnorder', compact('grnNo', 'companies', 'items'));
    }

    // Show list of all GRNs
    public function grnDetails()
    {
        $grns = Grn::with('products')->orderBy('id', 'desc')->get();
        $companies = CustomerVendor::all();
        return view('superadmin.grn.grndetails', compact('grns', 'companies'));
    }

    // 1. Get all unused Sales and Purchase Order IDs
    public function availableOrders()
    {
        // Get all order_nos already in GRN table
        $usedOrderNos = \App\Models\Grn::pluck('order_no')->toArray();

        $salesOrders = \App\Models\SalesOrder::whereNotIn('sales_order_no', $usedOrderNos)
            ->select('sales_order_no as order_no', 'sales_order_date', DB::raw("'sales' as order_type"))
            ->get();

        $purchaseOrders = \App\Models\PurchaseOrder::whereNotIn('purchase_order_no', $usedOrderNos)
            ->select('purchase_order_no as order_no', 'purchase_order_date as order_date', DB::raw("'purchase' as order_type"))
            ->get();

        $orders = $salesOrders->concat($purchaseOrders)->values();
        return response()->json($orders);
    }

    // 2. Get full details for a given order_no and type
    public function orderDetails(Request $request)
    {
        $type = $request->query('type');
        $orderNo = $request->query('order_no');
        if ($type === 'sales') {
            $order = \App\Models\SalesOrder::where('sales_order_no', $orderNo)->with('customer')->where('status','approved')->first();
        } else {
            $order = \App\Models\PurchaseOrder::where('purchase_order_no', $orderNo)->with('vendor')->where('status','approved')->first();
        }
        if (!$order) {
            return response()->json(['error' => 'Order not found'], 404);
        }
        return response()->json($order);
    }

    /**
     * Get available Purchase Invoices that haven't been linked to a GRN
     */
    public function availablePurchaseInvoices()
    {
        // Get purchase invoice IDs already linked to GRNs
        $usedInvoiceIds = Grn::whereNotNull('purchase_invoice_id')->pluck('purchase_invoice_id')->toArray();

        $invoices = \App\Models\Purchase::with('party')
            ->whereNotIn('id', $usedInvoiceIds)
            ->select('id', 'purchase_no', 'purchase_date', 'vendor_id', 'vendor_invoice_no', 'grand_total')
            ->orderBy('id', 'desc')
            ->get()
            ->map(function ($invoice) {
                return [
                    'id' => $invoice->id,
                    'purchase_no' => $invoice->purchase_no,
                    'purchase_date' => $invoice->purchase_date,
                    'vendor_invoice_no' => $invoice->vendor_invoice_no,
                    'vendor_name' => $invoice->party ? $invoice->party->company : 'Unknown',
                    'grand_total' => $invoice->grand_total,
                ];
            });

        return response()->json($invoices);
    }

    /**
     * Get Purchase Invoice details by ID
     */
    public function purchaseInvoiceDetails($id)
    {
        $invoice = \App\Models\Purchase::with(['party', 'items.item'])->find($id);

        if (!$invoice) {
            return response()->json(['success' => false, 'message' => 'Purchase Invoice not found'], 404);
        }

        return response()->json([
            'success' => true,
            'invoice' => $invoice,
            'items' => $invoice->items->map(function ($item) {
                return [
                    'description' => $item->description ?? ($item->item ? $item->item->item_name : ''),
                    'quantity' => $item->quantity,
                    'unit' => $item->uom ?? 'Nos',
                    'rate' => $item->rate,
                    'amount' => $item->amount,
                ];
            }),
        ]);
    }

    /**
     * Search stock items for searchable dropdown (Select2)
     */
    public function searchStockItems(Request $request)
    {
        $search = $request->get('q', '');

        $items = \App\Models\StockItem::with('category')
            ->when($search, function ($query) use ($search) {
                $query->where('item_name', 'like', "%{$search}%");
            })
            ->limit(20)
            ->get()
            ->map(function ($item) {
                return [
                    'id' => $item->item_name, // Use item_name as the value to submit
                    'text' => $item->item_name . ($item->category ? ' (' . $item->category->name . ')' : ''),
                    'item_name' => $item->item_name,
                    'uom' => $item->uom,
                    'stock_item_id' => $item->id,
                ];
            });

        return response()->json(['results' => $items]);
    }

    // Store a new GRN
    public function store(Request $request)
    {
        $validated = $request->validate([
            'grn_no' => 'required|unique:grns,grn_no',
            'grn_date' => 'required|date',
            'order_no' => 'nullable',
            'order_date' => 'nullable|date',
            'purchase_invoice_id' => 'nullable|exists:purchases,id', // Added for Purchase Invoice reference
            'company_name' => 'required',
            'product_type' => 'nullable|string',
            'challan' => 'nullable|file|mimes:pdf|max:2048',
            'products.*.sku_id' => 'nullable',
            'products.*.description' => 'required|string',
            'products.*.quantity' => 'required|numeric',
            'products.*.unit' => 'required|string',
            'products.*.date' => 'required|date',
        ]);

        // Handle Challan file
        $challanPath = null;
        if ($request->hasFile('challan')) {
            $challanPath = $request->file('challan')->store('challans', 'public');
        }

        $grn = Grn::create([
            'grn_no' => $request->grn_no,
            'grn_date' => $request->grn_date,
            'order_no' => $request->order_no,
            'order_date' => $request->order_date,
            'purchase_invoice_id' => $request->purchase_invoice_id, // Added for Purchase Invoice reference
            'company_name' => $request->company_name,
            'order_ref_no' => $request->order_ref_no,
            'company_address' => $request->company_address,
            'company_gst' => $request->company_gstn,
            'company_email' => $request->company_email,
            'company_phone' => $request->company_phone,
            'quotation_no' => $request->quotation_no,
            'quotation_date' => $request->quotation_date,
            'rfq_no' => $request->rfq_no,
            'rfq_date' => $request->rfq_date,
            'part_no' => $request->part_no,
            'project_material_no' => $request->project_material_no,
            'drawing_no' => $request->drawing_no,
            'drawing_rev' => $request->drawing_rev,
            'description' => $request->description,
            'product_type' => $request->product_type,
            'challan_file' => $challanPath,
        ]);

        foreach ($request->products as $index => $product) {
            GrnProductDetail::create([
                'grn_id' => $grn->id,
                'sl_no' => $index + 1,
                'sku_id' => $product['sku_id'] ?? null,
                'stock_item_id' => $product['stock_item_id'] ?? null,
                'description' => $product['description'],
                'quantity' => $product['quantity'],
                'unit' => $product['unit'],
                'date' => $product['date'],
                'supplier' => $product['supplier'] ?? null,
                'remarks' => $product['remarks'] ?? null,
            ]);
        }

        return redirect()->route('superadmin.grn.grnorder')->with('success', 'GRN saved successfully!');
    }

    // Edit GRN (show edit form)
    public function edit($id)
    {
        $grn = Grn::with('products')->findOrFail($id);
        $companies = CustomerVendor::all();
        return view('superadmin.grn.edit', compact('grn', 'companies'));
    }

    // Update GRN
    public function update(Request $request, $id)
    {
        $grn = Grn::findOrFail($id);

        $grn->update($request->only([
            'grn_date',
            'order_no',
            'order_date',
            'company_name',
            'order_ref_no',
            'company_address',
            'company_gst',
            'company_email',
            'company_phone',
            'quotation_no',
            'quotation_date',
            'rfq_no',
            'rfq_date',
            'part_no',
            'project_material_no',
            'drawing_no',
            'drawing_rev',
            'description',
            'product_type'
        ]));

        if ($request->hasFile('challan')) {
            $path = $request->file('challan')->store('challans', 'public');
            $grn->update(['challan_file' => $path]);
        }

        // Delete old products
        GrnProductDetail::where('grn_id', $grn->id)->delete();

        foreach ($request->products as $index => $product) {
            GrnProductDetail::create([
                'grn_id' => $grn->id,
                'sl_no' => $index + 1,
                'stock_item_id' => $product['stock_item_id'] ?? null,
                'description' => $product['description'],
                'quantity' => $product['quantity'],
                'unit' => $product['unit'],
                'date' => $product['date'],
                'supplier' => $product['supplier'] ?? null,
                'remarks' => $product['remarks'] ?? null,
            ]);
        }

        return redirect()->route('superadmin.grn.grndetails')->with('success', 'GRN updated successfully.');
    }

    // Show GRN details (view)
    public function show($id)
    {
        $grn = Grn::with('products')->findOrFail($id);
        return view('superadmin.grn.view', compact('grn'));
    }

    // Delete GRN
    public function destroy($id)
    {
        $grn = Grn::findOrFail($id);
        $grn->products()->delete();
        $grn->delete();

        return response()->json(['success' => true]);
    }

    // Import GRNs from Excel
    public function import(Request $request)
    {
        $request->validate([
            'file' => 'required|mimes:xls,xlsx'
        ]);

        try {
            $file = $request->file('file');
            $spreadsheet = IOFactory::load($file->getRealPath());
            $sheet = $spreadsheet->getActiveSheet();
            $rows = $sheet->toArray();

            $header = array_shift($rows);

            foreach ($rows as $row) {
                $data = array_combine($header, $row);

                if (empty($data['grn_no'])) continue;

                Grn::updateOrCreate(
                    ['grn_no' => $data['grn_no']],
                    [
                        'grn_date' => $data['grn_date'],
                        'order_no' => $data['order_no'],
                        'order_date' => $data['order_date'],
                        'company_name' => $data['company_name'],
                        'order_ref_no' => $data['order_ref_no'],
                        'company_address' => $data['company_address'],
                        'company_gst' => $data['company_gstn'],
                        'company_email' => $data['company_email'],
                        'company_phone' => $data['company_phone'],
                        'quotation_no' => $data['quotation_no'],
                        'quotation_date' => $data['quotation_date'],
                        'rfq_no' => $data['rfq_no'],
                        'rfq_date' => $data['rfq_date'],
                        'part_no' => $data['part_no'],
                        'project_material_no' => $data['project_material_no'],
                        'drawing_no' => $data['drawing_no'],
                        'drawing_rev' => $data['drawing_rev'],
                        'description' => $data['description'],
                        'product_type' => $data['product_type'],
                    ]
                );
            }

            return redirect()->back()->with('success', 'GRNs imported successfully.');
        } catch (\Throwable $e) {
            Log::error('GRN Import Error: ' . $e->getMessage());
            return redirect()->back()->with('error', 'Failed to import: ' . $e->getMessage());
        }
    }
    // Approve GRN and Update Stock
    public function approve($id)
    {
        $grn = Grn::with('products')->findOrFail($id);

        if ($grn->status === 'approved') {
            return response()->json(['success' => false, 'message' => 'GRN already approved.']);
        }

        if ($grn->status === 'rejected') {
            return response()->json(['success' => false, 'message' => 'Cannot approve a rejected GRN.']);
        }

        DB::beginTransaction();
        try {
            $processedItems = [];
            $createdItems = [];
            $skippedItems = [];

            foreach ($grn->products as $product) {
                // Skip if no description
                if (empty($product->description)) {
                    $skippedItems[] = "Row {$product->sl_no}: No description provided";
                    continue;
                }

                // Step 1: Try to find SKU by sku_id (if saved)
                $sku = null;
                if (!empty($product->sku_id)) {
                    $sku = SkuMaster::find($product->sku_id);
                }

                // Step 2: Try to find SKU by item_name matching description
                if (!$sku && !empty($product->description)) {
                    $sku = SkuMaster::where('item_name', $product->description)->first();
                }

                // Step 3: If not found in SkuMaster, check StockItem and create SkuMaster
                if (!$sku && !empty($product->description)) {
                    $stockItem = \App\Models\StockItem::where('item_name', $product->description)->first();

                    if ($stockItem) {
                        // Create SkuMaster from StockItem
                        $sku = SkuMaster::create([
                            'item_name' => $stockItem->item_name,
                            'category' => $stockItem->category ? $stockItem->category->name : null,
                            'uom' => $stockItem->uom ?? $product->unit,
                            'tax_rate' => ($stockItem->sgst ?? 0) + ($stockItem->cgst ?? 0) + ($stockItem->igst ?? 0),
                            'current_stock' => 0,
                            'supplier_name' => $grn->company_name,
                        ]);
                        $createdItems[] = $stockItem->item_name;
                    }
                }

                // Step 4: If still not found, create new SkuMaster from GRN product details
                if (!$sku) {
                    $sku = SkuMaster::create([
                        'item_name' => $product->description,
                        'category' => null,
                        'uom' => $product->unit,
                        'current_stock' => 0,
                        'supplier_name' => $product->supplier ?? $grn->company_name,
                    ]);
                    $createdItems[] = $product->description;
                }

                // Now update stock
                $oldStock = $sku->current_stock ?? 0;
                $sku->current_stock = $oldStock + $product->quantity;
                $sku->save();

                // Update GrnProductDetail with sku_id for future reference
                $product->sku_id = $sku->id;
                $product->save();

                // Log Movement
                \App\Models\SkuMovement::create([
                    'reference' => $grn->grn_no,
                    'sku_id' => $sku->id,
                    'product' => $sku->item_name,
                    'type' => 'inbound',
                    'quantity' => $product->quantity,
                    'from_location' => $grn->company_name ?? 'Vendor',
                    'to_location' => 'Inventory',
                    'date' => now(),
                    'status' => 'completed',
                    'notes' => 'GRN Approval - Stock updated from ' . $oldStock . ' to ' . $sku->current_stock
                ]);

                $processedItems[] = $sku->item_name . ' (+' . $product->quantity . ' ' . $product->unit . ')';
            }

            // Update GRN status
            $grn->update(['status' => 'approved']);

            DB::commit();

            // Build success message
            $message = 'GRN Approved successfully!';
            if (count($processedItems) > 0) {
                $message .= ' Stock updated for ' . count($processedItems) . ' item(s).';
            }
            if (count($createdItems) > 0) {
                $message .= ' Created ' . count($createdItems) . ' new SKU(s).';
            }
            if (count($skippedItems) > 0) {
                $message .= ' Skipped ' . count($skippedItems) . ' item(s).';
            }

            return response()->json([
                'success' => true,
                'message' => $message,
                'details' => [
                    'processed' => $processedItems,
                    'created' => $createdItems,
                    'skipped' => $skippedItems
                ]
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('GRN Approval Error: ' . $e->getMessage() . ' | Stack: ' . $e->getTraceAsString());
            return response()->json(['success' => false, 'message' => 'Error approving GRN: ' . $e->getMessage()]);
        }
    }

    /**
     * Reject a GRN
     */
    public function reject(Request $request, $id)
    {
        $grn = Grn::findOrFail($id);

        if ($grn->status === 'rejected') {
            return response()->json(['success' => false, 'message' => 'GRN already rejected.']);
        }

        if ($grn->status === 'approved') {
            return response()->json(['success' => false, 'message' => 'Cannot reject an approved GRN.']);
        }

        try {
            $grn->update([
                'status' => 'rejected',
            ]);

            return response()->json(['success' => true, 'message' => 'GRN rejected successfully.']);
        } catch (\Exception $e) {
            Log::error('GRN Rejection Error: ' . $e->getMessage());
            return response()->json(['success' => false, 'message' => 'Error rejecting GRN.']);
        }
    }

    /**
     * Download GRN import template
     */
    public function downloadTemplate()
    {
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        // Set headers
        $headers = [
            'GRN No', 'GRN Date', 'Order No', 'Order Date', 'Company Name',
            'Company Address', 'GST No', 'Email', 'Phone',
            'Quotation No', 'Quotation Date', 'RFQ No', 'RFQ Date',
            'Part No', 'Project/Material No', 'Drawing No', 'Drawing Rev',
            'Description', 'Product Type',
            'Item Description', 'Quantity', 'UOM', 'Supplier', 'Remarks'
        ];

        $sheet->fromArray($headers, NULL, 'A1');

        // Style headers
        $sheet->getStyle('A1:Y1')->applyFromArray([
            'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
            'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => '4E73DF']],
        ]);

        // Add sample data row
        $sheet->fromArray([
            'UEPL/GRN/0001', date('Y-m-d'), 'PO-001', date('Y-m-d'), 'Sample Company',
            '123 Sample Street', '29AAAAA0000A1Z5', 'sample@email.com', '9876543210',
            'QT-001', date('Y-m-d'), 'RFQ-001', date('Y-m-d'),
            'PART-001', 'PROJ-001', 'DRW-001', 'Rev-A',
            'Sample Description', 'Raw Material',
            'Item 1', '10', 'Nos', 'Supplier Name', 'Remarks'
        ], NULL, 'A2');

        // Auto-size columns
        foreach (range('A', 'Y') as $col) {
            $sheet->getColumnDimension($col)->setAutoSize(true);
        }

        $writer = IOFactory::createWriter($spreadsheet, 'Xlsx');

        $filename = 'GRN_Import_Template.xlsx';

        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Cache-Control: max-age=0');

        $writer->save('php://output');
        exit;
    }
}
