<?php

namespace App\Http\Controllers\Tenant;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Tenant\ProductVariant;
use App\Models\Tenant\StockMovement;
use App\Models\Tenant\Product;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\Tenant\StockInImport;

use App\Models\Tenant\Purchase;
use App\Models\Tenant\PurchaseRequisition;
use App\Models\Tenant\Supplier;
use App\Models\Tenant\Brand;
use App\Models\Tenant\Manufacturer;
use App\Models\Tenant\Unit;
use App\Models\Tenant\ProductUnit;
use App\Models\Tenant\PurchaseItem;
use App\Models\Tenant\StoreLocation;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class StockInController extends Controller
{
    public function index()
    {
        $suppliers = Supplier::on('tenant')->get();
        $brands = Brand::on('tenant')->get();
        $manufacturers = Manufacturer::on('tenant')->get();
        $units = Unit::on('tenant')->get();
        $locations = StoreLocation::on('tenant')->get();
        
        // Ensure "Outsourcing" supplier exists or handle it in the view
        $defaultSupplier = Supplier::on('tenant')->where('name', 'Outsourcing')->first();

        // Auto Generate MRR No
        $mrrNo = $this->generateMrrNo();

        return view('tenant.stock.in', compact(
            'suppliers', 
            'brands', 
            'manufacturers', 
            'units',
            'locations',
            'defaultSupplier',
            'mrrNo'
        ));
    }

    public function report($id)
    {
        $purchase = Purchase::on('tenant')
            ->with(['items.variant.product', 'supplier', 'items.location', 'items.brand', 'items.manufacturer', 'items.unit'])
            ->findOrFail($id);
            
        return view('tenant.stock.report', compact('purchase'));
    }

    private function generateMrrNo()
    {
        $prefix = 'MRR-' . date('ym') . '-';
        
        $lastPurchase = Purchase::on('tenant')
            ->where('mrr_no', 'like', $prefix . '%')
            ->orderBy('id', 'desc')
            ->first();

        if ($lastPurchase) {
            $lastNo = (int) substr($lastPurchase->mrr_no, strlen($prefix));
            $newNo = str_pad($lastNo + 1, 6, '0', STR_PAD_LEFT);
        } else {
            $newNo = '000001';
        }

        return $prefix . $newNo;
    }

    public function mrrIndex()
    {
        $requisitions = PurchaseRequisition::on('tenant')
            ->where('status', 'approved')
            ->with('supplier')
            ->latest()
            ->get();
        return view('tenant.stock.mrr_index', compact('requisitions'));
    }

    public function mrrCreate($requisitionId = null)
    {
        $requisition = null;
        if ($requisitionId) {
            $requisition = PurchaseRequisition::on('tenant')
                ->with(['items.variant.product', 'supplier'])
                ->findOrFail($requisitionId);
            
            if ($requisition->status !== 'approved') {
                return redirect()->route('tenant.stock.mrr.index')->with('error', 'Only approved requisitions can be processed.');
            }
        }

        $suppliers = Supplier::on('tenant')->get();
        $products = ProductVariant::on('tenant')->with('product')->get();

        return view('tenant.stock.mrr_create', compact('requisition', 'suppliers', 'products'));
    }

    public function mrrStore(Request $request)
    {
        $validated = $request->validate([
            'purchase_requisition_id' => 'nullable|exists:tenant.purchase_requisitions,id',
            'supplier_id' => 'required|exists:tenant.suppliers,id',
            'mrr_no' => 'required|string|unique:tenant.purchases,mrr_no',
            'challan_no' => 'required|string',
            'items' => 'required|array|min:1',
            'items.*.variant_id' => 'required|exists:tenant.product_variants,id',
            'items.*.quantity' => 'required|numeric|min:0.01',
            'items.*.unit_cost' => 'required|numeric|min:0',
            'notes' => 'nullable|string',
        ]);

        try {
            DB::connection('tenant')->transaction(function () use ($validated) {
                $totalAmount = 0;
                foreach ($validated['items'] as $item) {
                    $totalAmount += $item['quantity'] * $item['unit_cost'];
                }

                $purchase = Purchase::on('tenant')->create([
                    'purchase_no' => 'PO-' . strtoupper(uniqid()),
                    'mrr_no' => $validated['mrr_no'],
                    'challan_no' => $validated['challan_no'],
                    'purchase_requisition_id' => $validated['purchase_requisition_id'],
                    'supplier_id' => $validated['supplier_id'],
                    'total_amount' => $totalAmount,
                    'paid_amount' => 0, // MRR usually doesn't handle payment immediately
                    'status' => 'received',
                    'notes' => $validated['notes'] ?? null,
                ]);

                foreach ($validated['items'] as $item) {
                    $purchase->items()->create([
                        'variant_id' => $item['variant_id'],
                        'quantity' => $item['quantity'],
                        'cost' => $item['unit_cost'],
                        'total' => $item['quantity'] * $item['unit_cost'],
                    ]);

                    // Update Stock
                    $variant = ProductVariant::on('tenant')->find($item['variant_id']);
                    $oldStock = $variant->stock;
                    $variant->increment('stock', $item['quantity']);
                    
                    // Update cost
                    $variant->update(['cost' => $item['unit_cost']]);

                    // Record movement
                    StockMovement::record(
                        $item['variant_id'],
                        $item['quantity'],
                        'purchase',
                        'purchase',
                        $purchase->id,
                        "MRR #{$validated['mrr_no']} - Challan #{$validated['challan_no']} (Stock: {$oldStock} → " . ($oldStock + $item['quantity']) . ")"
                    );
                }

                if ($validated['purchase_requisition_id']) {
                    PurchaseRequisition::on('tenant')
                        ->where('id', $validated['purchase_requisition_id'])
                        ->update(['status' => 'received']);
                }
            });

            return redirect()->route('tenant.purchases.index')->with('success', 'MRR processed and stock updated successfully.');
        } catch (\Exception $e) {
            return back()->with('error', 'Failed to process MRR: ' . $e->getMessage())->withInput();
        }
    }

    public function searchMrrs(Request $request)
    {
        $term = $request->get('q');
        
        $query = Purchase::on('tenant')->with('supplier');

        if (!empty($term)) {
            $query->where(function($q) use ($term) {
                $q->where('mrr_no', 'LIKE', "%{$term}%")
                  ->orWhere('purchase_no', 'LIKE', "%{$term}%")
                  ->orWhere('challan_no', 'LIKE', "%{$term}%");
            });
        }

        $purchases = $query->orderBy('id', 'desc')
            ->limit(20)
            ->get();

        $results = [];
        foreach ($purchases as $purchase) {
            $supplierName = $purchase->supplier->name ?? 'No Supplier';
            $date = $purchase->created_at ? $purchase->created_at->format('d M Y') : 'No Date';
            
            // Format the text to show more info
            $displayText = ($purchase->mrr_no ?: $purchase->purchase_no ?: 'ID: ' . $purchase->id);
            if ($purchase->challan_no) {
                $displayText .= " (Challan: {$purchase->challan_no})";
            }
            $displayText .= " - {$supplierName} [{$date}]";

            $results[] = [
                'id' => $purchase->id,
                'text' => $displayText,
            ];
        }

        if (empty($results)) {
            $totalCount = Purchase::on('tenant')->count();
            if (empty($term)) {
                return response()->json([
                    ['id' => '', 'text' => "No MRR records found. Total records in system: {$totalCount}", 'disabled' => true]
                ]);
            } else {
                return response()->json([
                    ['id' => '', 'text' => "No results for '{$term}'. Total records in system: {$totalCount}", 'disabled' => true]
                ]);
            }
        }

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

    public function searchProducts(Request $request)
    {
        $term = $request->get('q');
        
        // We use ProductVariant as the base because Stock In is per variant
        $query = ProductVariant::on('tenant')
            ->join('products', 'product_variants.product_id', '=', 'products.id')
            ->leftJoin('brands', 'products.brand_id', '=', 'brands.id')
            ->leftJoin('categories', 'products.category_id', '=', 'categories.id')
            ->select(
                'product_variants.id',
                'product_variants.name as variant_name',
                'product_variants.sku as variant_sku',
                'products.name as product_name',
                'products.id as product_id',
                'products.manufacturer_id',
                'products.brand_id',
                'products.unit_id',
                'brands.name as brand_name',
                'categories.name as category_name'
            );

        if (!empty($term)) {
            $query->where(function($q) use ($term) {
                $q->where('products.name', 'LIKE', "%{$term}%")
                  ->orWhere('product_variants.name', 'LIKE', "%{$term}%")
                  ->orWhere('product_variants.sku', 'LIKE', "%{$term}%");
            });
        }
        
        $variants = $query->orderBy('products.name', 'asc')
                          ->limit(50)
                          ->get();

        $results = [];
        foreach ($variants as $variant) {
            $displayText = $variant->product_name;
            
            // Append variant name if it's different from product name
            if ($variant->variant_name && $variant->variant_name !== $variant->product_name) {
                $displayText .= ' - ' . $variant->variant_name;
            }
            
            // Append SKU
            if ($variant->variant_sku) {
                $displayText .= ' (' . $variant->variant_sku . ')';
            }
            
            // Append Category/Brand for better identification (like in products list)
            $meta = [];
            if ($variant->category_name) $meta[] = $variant->category_name;
            if ($variant->brand_name) $meta[] = $variant->brand_name;
            
            if (!empty($meta)) {
                $displayText .= ' [' . implode(', ', $meta) . ']';
            }

            $results[] = [
                'id' => $variant->id,
                'text' => $displayText,
                'product_id' => $variant->product_id,
                'manufacturer_id' => $variant->manufacturer_id ?? 'n/a',
                'brand_id' => $variant->brand_id ?? 'n/a',
                'unit_id' => $variant->unit_id,
            ];
        }

        if (empty($results) && empty($term)) {
            // Check if there are ANY products at all for debugging
            $totalCount = Product::on('tenant')->count();
            if ($totalCount == 0) {
                return response()->json([
                    ['id' => '', 'text' => 'No products found. Please add products first.', 'disabled' => true]
                ]);
            }
        }

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

    public function store(Request $request)
    {
        $request->validate([
            'location_id' => 'nullable|exists:tenant.store_locations,id',
            'supplier_id' => 'nullable',
            'mrr_no' => 'required|string',
            'challan_no' => 'required|string',
            'attachment' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:2048',
            'items' => 'required|array|min:1',
            'items.*.variant_id' => 'required|exists:tenant.product_variants,id',
            'items.*.quantity' => 'required|numeric|min:0.01',
            'items.*.unit_price' => 'required|numeric|min:0',
            'items.*.unit_id' => 'required|exists:tenant.units,id',
        ]);

        try {
            DB::connection('tenant')->beginTransaction();

            // Handle Supplier
            $supplierId = $request->supplier_id;
            if ($supplierId === 'outsourcing') {
                $supplier = Supplier::on('tenant')->firstOrCreate(['name' => 'Outsourcing']);
                $supplierId = $supplier->id;
            } elseif (!$supplierId) {
                $supplierId = null;
            }

            // Handle Attachment
            $attachmentPath = null;
            if ($request->hasFile('attachment')) {
                $attachmentPath = $request->file('attachment')->store('tenant/attachments', 'public');
            }

            // Create Purchase (Stock In / MRR)
            $purchase = Purchase::on('tenant')->create([
                'location_id' => $request->location_id,
                'supplier_id' => $supplierId,
                'purchase_no' => $request->mrr_no, // Use MRR No as Purchase No
                'mrr_no' => $request->mrr_no,
                'challan_no' => $request->challan_no,
                'attachment' => $attachmentPath,
                'notes' => $request->notes,
                'total_amount' => collect($request->items)->sum(function($item) {
                    return $item['quantity'] * $item['unit_price'];
                }),
                'status' => 'received',
            ]);

            foreach ($request->items as $item) {
                $variant = ProductVariant::on('tenant')->findOrFail($item['variant_id']);
                
                // Create Purchase Item
                PurchaseItem::on('tenant')->create([
                    'purchase_id' => $purchase->id,
                    'variant_id' => $variant->id,
                    'quantity' => $item['quantity'],
                    'cost' => $item['unit_price'],
                    'unit_id' => $item['unit_id'],
                    'location_id' => $request->location_id, // Same location for all items
                    'manufacturer_id' => isset($item['manufacturer_id']) && $item['manufacturer_id'] !== 'n/a' ? $item['manufacturer_id'] : null,
                    'brand_id' => isset($item['brand_id']) && $item['brand_id'] !== 'n/a' ? $item['brand_id'] : null,
                    'total' => $item['quantity'] * $item['unit_price'],
                ]);

                // Update Stock
                $variant->increment('stock', $item['quantity']);
                
                // Record Stock Movement
                StockMovement::on('tenant')->create([
                    'variant_id' => $variant->id,
                    'quantity' => $item['quantity'],
                    'movement_type' => 'purchase',
                    'reference_type' => 'purchase',
                    'reference_id' => $purchase->id,
                    'user_id' => auth()->id(),
                    'notes' => "Stock In via MRR: {$request->mrr_no}. Challan: {$request->challan_no}",
                ]);
            }

            DB::connection('tenant')->commit();
            return redirect()->route('tenant.stock.in.report', $purchase->id)->with('success', "Stock In processed successfully with MRR: {$request->mrr_no}");

        } catch (\Exception $e) {
            DB::connection('tenant')->rollBack();
            return back()->with('error', 'Error processing stock in: ' . $e->getMessage())->withInput();
        }
    }

    public function import(Request $request)
    {
        $request->validate([
            'file' => 'required|mimes:xlsx,xls,csv|max:2048',
        ]);

        try {
            Excel::import(new StockInImport, $request->file('file'));
            return redirect()->route('tenant.stock.in.index')->with('success', 'Stock imported successfully!');
        } catch (\Exception $e) {
            return back()->with('error', 'Import failed: ' . $e->getMessage());
        }
    }
}
