<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\InventoryItem;
use App\Models\Contact;
use App\Models\InventoryOrder;
use App\Models\InventoryIssue;
use App\Models\InventoryMovement;
use App\Http\Controllers\Concerns\ResolvesTenantHotel;
use App\Services\CategoryPresetService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

class InventoryController extends Controller
{
    use ResolvesTenantHotel;

    public function __construct()
    {
        // Set default timezone for inventory operations
        date_default_timezone_set('Africa/Kampala');
    }

    private function getHotelId()
    {
        return $this->tenantHotelIdOrAbort();
    }

    /**
     * Display a listing of the inventory items.
     */
    public function index(Request $request)
    {
        $hotelId = $this->getHotelId();
        $query = InventoryItem::where('hotel_id', $hotelId);
        
        // Search functionality
        if ($request->has('search') && !empty($request->search)) {
            $query->where('name', 'like', '%' . $request->search . '%');
        }
        
        // Category filter
        if ($request->has('category') && !empty($request->category)) {
            $query->where('category', $request->category);
        }
        
        // Department filter (if exists)
        if ($request->has('department') && !empty($request->department)) {
            $query->where('department', $request->department);
        }
        
        // Status filter
        if ($request->has('status') && !empty($request->status)) {
            if ($request->status == 'in_stock') {
                $query->where('quantity', '>', DB::raw('min_stock'));
            } elseif ($request->status == 'low_stock') {
                $query->where('quantity', '<=', DB::raw('min_stock'))
                      ->where('quantity', '>', 0);
            } elseif ($request->status == 'out_of_stock') {
                $query->where('quantity', 0);
            } elseif ($request->status == 'active') {
                // Check if active column exists
                if (Schema::hasColumn('inventory_items', 'active')) {
                    $query->where('active', true);
                }
            } elseif ($request->status == 'inactive') {
                if (Schema::hasColumn('inventory_items', 'active')) {
                    $query->where('active', false);
                }
            }
        }
        
        // Sorting
        if ($request->has('sort')) {
            switch ($request->sort) {
                case 'name_desc':
                    $query->orderBy('name', 'desc');
                    break;
                case 'quantity_asc':
                    $query->orderBy('quantity', 'asc');
                    break;
                case 'quantity_desc':
                    $query->orderBy('quantity', 'desc');
                    break;
                case 'value_desc':
                    $query->orderBy(DB::raw('quantity * unit_price'), 'desc');
                    break;
                case 'recent':
                    $query->orderBy('created_at', 'desc');
                    break;
                default:
                    $query->orderBy('name', 'asc');
            }
        } else {
            $query->orderBy('name', 'asc');
        }
        
        $items = $query->paginate(10);
        
        // Calculate statistics - SIMPLIFIED VERSION
        $totalItems = InventoryItem::where('hotel_id', $hotelId)->count();
        $totalValue = InventoryItem::get()->sum(function($item) {
            return $item->quantity * $item->unit_price;
        });
        $lowStockCount = InventoryItem::where('quantity', '<=', DB::raw('min_stock'))
                                    ->where('quantity', '>', 0)
                                    ->count();
        $outOfStockCount = InventoryItem::where('quantity', 0)->count();
        $inStockCount = InventoryItem::where('quantity', '>', DB::raw('min_stock'))->count();
        
        // Set defaults for view variables
        $valueChange = "0.0"; // Default value
        $activeItems = $totalItems; // All items are active by default
        $inactiveItems = 0;
        $criticalCount = 0;
        $pendingOrders = 0;
        $pendingOrdersValue = 0;
        $overdueOrders = 0;
        $recentActivities = collect(); // Empty collection
        $lowStockItems = InventoryItem::where('quantity', '<=', DB::raw('min_stock'))
                                     ->where('quantity', '>', 0)
                                     ->orderBy('quantity')
                                     ->get();
        $reorderItems = InventoryItem::where('hotel_id', $hotelId)
            ->whereRaw('quantity <= COALESCE(reorder_point, min_stock)')
            ->orderBy('quantity')
            ->limit(5)
            ->get();
        $recentIssues = InventoryIssue::where('hotel_id', $hotelId)
            ->with(['item', 'issuer', 'approver'])
            ->latest('issued_at')
            ->limit(8)
            ->get();
        
        // Shared preset + hotel categories (aligned with vendor module)
        app(CategoryPresetService::class)->ensurePresetsForHotel($hotelId ? (int) $hotelId : null);
        $categories = \App\Models\Category::where('hotel_id', $hotelId)->where('active', true)->orderBy('name')->pluck('name');
        $suppliers = Contact::where('hotel_id', $hotelId)->where('type', 'vendor')->get();
        
        // Calculate average delivery time (default value)
        $avgDeliveryTime = 7;
        
        // Get all items for "All Items" modal
        $allItems = InventoryItem::all();
        
        return view('inventory.index', compact(
            'items',
            'totalItems',
            'totalValue',
            'lowStockCount',
            'outOfStockCount',
            'inStockCount',
            'valueChange',
            'activeItems',
            'inactiveItems',
            'criticalCount',
            'pendingOrders',
            'pendingOrdersValue',
            'overdueOrders',
            'recentActivities',
            'lowStockItems',
            'categories',
            'suppliers',
            'avgDeliveryTime',
            'allItems',
            'reorderItems',
            'recentIssues'
        ));
    }

    /**
     * Show the form for creating a new inventory item.
     */
    public function create()
    {
        $hotelId = $this->getHotelId();
        // Use just the category strings for easier consumption in views.
        $categories = InventoryItem::where('hotel_id', $hotelId)->select('category')->distinct()->pluck('category');
        $suppliers = Contact::where('hotel_id', $hotelId)->where('type', 'vendor')->get();
        
        return view('inventory.create', compact('categories', 'suppliers'));
    }

    /**
     * Store a newly created inventory item.
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|max:255',
            'category' => 'required',
            'quantity' => 'required|integer|min:0',
            'min_stock' => 'required|integer|min:0',
            'unit_price' => 'required|numeric|min:0',
            'department' => 'nullable|string|max:100',
            'description' => 'nullable|string',
            'max_stock' => 'nullable|integer|min:0',
            'reorder_point' => 'nullable|integer|min:0',
            'selling_price' => 'nullable|numeric|min:0',
            'supplier_id' => [
                'nullable',
                Rule::exists('contacts', 'id')->where(function ($query) {
                    $query->where('hotel_id', $this->getHotelId());
                }),
            ],
            'location' => 'nullable|string|max:255',
            'unit' => 'nullable|string|in:' . implode(',', array_keys(config('inventory_units.options', []))),
            'purchase_unit' => 'nullable|string|in:' . implode(',', array_keys(config('inventory_units.options', []))),
            'unit_conversion_factor' => 'nullable|numeric|min:0.001',
            'expiry_date' => 'nullable|date',
            'supplier' => 'nullable|max:255',
            'notes' => 'nullable'
        ]);

        $validated['hotel_id'] = $this->getHotelId();
        InventoryItem::create($validated);

        return redirect()->route('inventory.index')
                         ->with('success', 'Item added successfully.');
    }

    /**
     * Display the specified inventory item.
     */
    public function show(InventoryItem $inventoryItem)
    {
        return view('inventory.show', compact('inventoryItem'));
    }

    /**
     * Show the form for editing the specified inventory item.
     */
    public function edit(InventoryItem $inventoryItem)
    {
        return view('inventory.edit', compact('inventoryItem'));
    }

    /**
     * Update the specified inventory item.
     */
    public function update(Request $request, $inventoryItem)
    {
        $hotelId = $this->getHotelId();
        $inventoryItem = InventoryItem::where('hotel_id', $hotelId)->findOrFail($inventoryItem);

        $rules = [
            'name' => 'required|max:255',
            'category' => 'nullable|string|max:255',
            'quantity' => 'required|integer|min:0',
            'min_stock' => 'required|integer|min:0',
            'unit_price' => 'required|numeric|min:0',
            'department' => 'nullable|string|max:100',
            'description' => 'nullable|string',
            'max_stock' => 'nullable|integer|min:0',
            'reorder_point' => 'nullable|integer|min:0',
            'selling_price' => 'nullable|numeric|min:0',
            'supplier_id' => [
                'nullable',
                Rule::exists('contacts', 'id')->where(function ($query) {
                    $query->where('hotel_id', $this->getHotelId());
                }),
            ],
            'location' => 'nullable|string|max:255',
            // Keep update permissive to support legacy unit labels already in data.
            'unit' => 'nullable|string|max:50',
            'purchase_unit' => 'nullable|string|max:50',
            'unit_conversion_factor' => 'nullable|numeric|min:0.001',
            'expiry_date' => 'nullable|date',
            'supplier' => 'nullable|max:255',
            'notes' => 'nullable'
        ];

        $validator = Validator::make($request->all(), $rules);
        if ($validator->fails()) {
            return redirect()->route('inventory.index')
                ->withErrors($validator)
                ->withInput()
                ->with('error', 'Item update failed. Please check the form values and try again.');
        }

        $validated = $validator->validated();

        // If category text is edited directly, clear category_id so display uses the typed category.
        if (array_key_exists('category', $validated)) {
            $validated['category_id'] = null;
        }

        $inventoryItem->update($validated);

        return redirect()->route('inventory.index')->with('success', 'Item updated successfully.');
    }

    /**
     * Remove the specified inventory item.
     */
    public function destroy(InventoryItem $inventoryItem)
    {
        $inventoryItem->delete();

        return redirect()->route('inventory.index')
                         ->with('success', 'Item deleted successfully.');
    }

    /**
     * Get low stock items.
     */
    public function lowStock()
    {
        $items = InventoryItem::whereColumn('quantity', '<=', 'min_stock')
                             ->where('quantity', '>', 0)
                             ->orderBy('quantity')
                             ->get();

        return view('inventory.low-stock', compact('items'));
    }

    /**
     * Process inventory order.
     */
    public function order(Request $request, InventoryItem $inventoryItem)
    {
        $validated = $request->validate([
            'order_quantity' => 'required|integer|min:1'
        ]);

        $inventoryItem->increment('quantity', $validated['order_quantity']);

        return redirect()->route('inventory.index')
                         ->with('success', 'Order processed successfully.');
    }
    
    // In InventoryController.php
    public function showOrderForm($item)
    {
        $hotelId = $this->getHotelId();
        $item = InventoryItem::where('hotel_id', $hotelId)->findOrFail($item);
        
        // Get vendors that match the item's category
        $vendors = Contact::where('hotel_id', $hotelId)
                          ->where('vendor_category', $item->category)
                          ->where('active', true)
                          ->get();
        
        // Generate PO number
        $poNumber = 'PO-' . date('Ymd') . '-' . str_pad(InventoryOrder::where('hotel_id', $hotelId)->count() + 1, 4, '0', STR_PAD_LEFT);
        
        return view('inventory.order', compact('item', 'vendors', 'poNumber'));
    }

    public function processOrder(Request $request)
    {
        $hotelId = $this->getHotelId();

        $validated = $request->validate([
            'item_id' => [
                'required',
                Rule::exists('inventory_items', 'id')->where(function ($query) use ($hotelId) {
                    $query->where('hotel_id', $hotelId);
                }),
            ],
            'vendor_id' => [
                'required',
                Rule::exists('contacts', 'id')->where(function ($query) use ($hotelId) {
                    $query->where('hotel_id', $hotelId);
                }),
            ],
            'quantity' => 'required|integer|min:1',
            'urgency' => 'required|in:low,normal,high,urgent',
            'delivery_date' => 'nullable|date',
            'notes' => 'nullable|string'
        ]);

        DB::beginTransaction();

        try {
            // Process the order...
            $order = InventoryOrder::create([
                'hotel_id' => $hotelId,
                'item_id' => $request->item_id,
                'vendor_id' => $request->vendor_id,
                'quantity' => $request->quantity,
                'urgency' => $request->urgency,
                'delivery_date' => $request->delivery_date,
                'notes' => $request->notes,
                'status' => 'pending'
            ]);

            DB::commit();

            return redirect()->route('inventory.index')
                ->with('success', 'Order placed successfully!');

        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()
                ->with('error', 'Failed to place order: ' . $e->getMessage())
                ->withInput();
        }
    }
    
    public function export(Request $request, $format = 'csv')
    {
        $items = InventoryItem::where('hotel_id', $this->getHotelId())->get();
        
        if ($format === 'csv') {
            return $this->exportToCsv($items);
        } elseif ($format === 'excel') {
            return $this->exportToExcel($items);
        } elseif ($format === 'pdf') {
            return $this->exportToPdf($items);
        }
        
        return redirect()->back()->with('error', 'Invalid export format');
    }
    
    /**
     * Export to CSV
     */
    private function exportToCsv($items)
    {
        $fileName = 'inventory_' . date('Y-m-d') . '.csv';
        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="' . $fileName . '"',
        ];

        $callback = function() use ($items) {
            $file = fopen('php://output', 'w');
            
            // Add CSV headers
            fputcsv($file, [
                'Item Name', 
                'Category', 
                'Current Stock', 
                'Min Stock Level', 
                'Unit Price (UGX)', 
                'Total Value (UGX)', 
                'Status',
                'Supplier'
            ]);

            // Add data rows
            foreach ($items as $item) {
                $totalValue = $item->quantity * $item->unit_price;
                $status = $item->quantity > $item->min_stock ? 'In Stock' : 
                         ($item->quantity == 0 ? 'Out of Stock' : 'Low Stock');
                         
                fputcsv($file, [
                    $item->name,
                    $item->category,
                    $item->quantity,
                    $item->min_stock,
                    $item->unit_price,
                    $totalValue,
                    $status,
                    $item->supplier
                ]);
            }

            fclose($file);
        };

        return response()->stream($callback, 200, $headers);
    }
    
    /**
     * Export to Excel (simple implementation)
     */
    private function exportToExcel($items)
    {
        // For now, redirect to CSV as a simple solution
        return $this->exportToCsv($items);
    }
    
    /**
     * Export to PDF (simple implementation)
     */
    private function exportToPdf($items)
    {
        // Use dompdf to generate PDF from Blade view
        $pdf = \PDF::loadView('inventory.pdf', ['items' => $items]);
        $fileName = 'inventory_' . date('Y-m-d') . '.pdf';
        return $pdf->download($fileName);
    }

    /**
     * Quick stock adjustment (basic implementation)
     */
    public function quickAdjust(Request $request)
    {
        $hotelId = $this->getHotelId();

        $validated = $request->validate([
            'item_id' => [
                'required',
                Rule::exists('inventory_items', 'id')->where(function ($query) use ($hotelId) {
                    $query->where('hotel_id', $hotelId);
                }),
            ],
            'type' => 'required|in:add,remove,set',
            'quantity' => 'required|integer|min:1',
            'reason' => 'required|in:restock,damage,wastage,expiry,theft,count_adjustment,transfer_in,transfer_out,other',
            'notes' => 'nullable|string'
        ]);

        if (
            in_array($validated['type'], ['remove', 'set'], true) ||
            in_array($validated['reason'], ['damage', 'wastage', 'expiry', 'theft', 'count_adjustment', 'transfer_out', 'other'], true)
        ) {
            if (empty(trim((string) ($validated['notes'] ?? '')))) {
                return redirect()->back()
                    ->with('error', 'Please provide notes for this stock adjustment.')
                    ->withInput();
            }
        }
        
        DB::beginTransaction();
        
        try {
            $item = InventoryItem::where('hotel_id', $hotelId)->findOrFail($validated['item_id']);
            $previousQuantity = $item->quantity;
            
            switch ($validated['type']) {
                case 'add':
                    $newQuantity = $previousQuantity + $validated['quantity'];
                    break;
                    
                case 'remove':
                    $newQuantity = $previousQuantity - $validated['quantity'];
                    if ($newQuantity < 0) {
                        throw new \Exception('Cannot remove more stock than available.');
                    }
                    break;
                    
                case 'set':
                    $newQuantity = $validated['quantity'];
                    break;
            }
            
            // Update item quantity
            $item->update([
                'quantity' => $newQuantity
            ]);
            $this->logMovement($hotelId, $item, 'adjustment', $previousQuantity, $newQuantity - $previousQuantity, $newQuantity, 'QUICK-ADJUST', ucfirst($validated['reason']), $validated['notes'] ?? null);
            
            DB::commit();
            
            return redirect()->route('inventory.index')
                           ->with('success', 'Stock adjusted successfully (' . ucfirst($validated['reason']) . ').');
            
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()
                           ->with('error', 'Failed to adjust stock: ' . $e->getMessage())
                           ->withInput();
        }
    }

    /**
     * Create stock issue request (pending approval).
     */
    public function issueStock(Request $request)
    {
        $hotelId = $this->getHotelId();

        $validated = $request->validate([
            'inventory_item_id' => [
                'required',
                Rule::exists('inventory_items', 'id')->where(function ($query) use ($hotelId) {
                    $query->where('hotel_id', $hotelId);
                }),
            ],
            'quantity' => 'required|integer|min:1',
            'issued_to_name' => 'required|string|max:255',
            'issued_to_department' => 'nullable|string|max:100',
            'reason' => 'required|string|max:100',
            'notes' => 'nullable|string',
        ]);

        DB::beginTransaction();
        try {
            $item = InventoryItem::where('hotel_id', $hotelId)->findOrFail($validated['inventory_item_id']);

            InventoryIssue::create([
                'hotel_id' => $hotelId,
                'inventory_item_id' => $item->id,
                'quantity' => $validated['quantity'],
                'unit' => $item->unit,
                'issued_to_name' => $validated['issued_to_name'],
                'issued_to_department' => $validated['issued_to_department'] ?? null,
                'reason' => $validated['reason'],
                'status' => 'pending',
                'notes' => $validated['notes'] ?? null,
                'issued_by' => auth()->id(),
                'issued_at' => now(),
            ]);

            DB::commit();
            return redirect()->route('inventory.index')->with('success', 'Stock issue request submitted for approval.');
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()->with('error', 'Failed to issue stock: ' . $e->getMessage())->withInput();
        }
    }

    /**
     * Approve a pending stock issue request.
     */
    public function approveIssue(Request $request, $issueId)
    {
        $hotelId = $this->getHotelId();
        $issue = InventoryIssue::where('hotel_id', $hotelId)->findOrFail($issueId);

        if ($issue->status !== 'pending') {
            return redirect()->back()->with('error', 'Only pending requests can be approved.');
        }

        $issue->update([
            'status' => 'approved',
            'approved_by' => auth()->id(),
            'approved_at' => now(),
        ]);

        return redirect()->back()->with('success', 'Issue request approved. You can now issue and deduct stock.');
    }

    /**
     * Deduct stock for an approved issue request and mark as issued.
     */
    public function postIssue(Request $request, $issueId)
    {
        $hotelId = $this->getHotelId();
        $issue = InventoryIssue::where('hotel_id', $hotelId)->findOrFail($issueId);

        if ($issue->status !== 'approved') {
            return redirect()->back()->with('error', 'Only approved requests can be issued.');
        }

        DB::beginTransaction();
        try {
            $item = InventoryItem::where('hotel_id', $hotelId)->findOrFail($issue->inventory_item_id);

            if ($issue->quantity > $item->quantity) {
                throw new \Exception('Cannot issue more than available stock.');
            }

            $beforeQty = (int) $item->quantity;
            $item->decrement('quantity', $issue->quantity);
            $afterQty = $beforeQty - (int) $issue->quantity;
            $issue->update(['status' => 'issued']);
            $this->logMovement($hotelId, $item, 'out', $beforeQty, -1 * (int) $issue->quantity, $afterQty, 'ISSUE-' . $issue->id, $issue->reason, $issue->notes);

            DB::commit();
            return redirect()->back()->with('success', 'Stock issued and quantity reduced successfully.');
        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()->with('error', 'Failed to issue approved request: ' . $e->getMessage());
        }
    }

    /**
     * Reject a pending stock issue request.
     */
    public function rejectIssue(Request $request, $issueId)
    {
        $hotelId = $this->getHotelId();
        $issue = InventoryIssue::where('hotel_id', $hotelId)->findOrFail($issueId);

        if ($issue->status !== 'pending') {
            return redirect()->back()->with('error', 'Only pending requests can be rejected.');
        }

        $validated = $request->validate([
            'rejection_reason' => 'required|string|max:500',
        ]);

        $issue->update([
            'status' => 'rejected',
            'rejected_by' => auth()->id(),
            'rejected_at' => now(),
            'rejection_reason' => $validated['rejection_reason'],
        ]);

        return redirect()->back()->with('success', 'Issue request rejected.');
    }

    /**
     * Show stock issue audit page with filters.
     */
    public function issues(Request $request)
    {
        $hotelId = $this->getHotelId();
        $query = InventoryIssue::where('hotel_id', $hotelId)->with(['item', 'issuer', 'approver']);

        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }
        if ($request->filled('department')) {
            $query->where('issued_to_department', $request->department);
        }
        if ($request->filled('item_id')) {
            $query->where('inventory_item_id', $request->item_id);
        }
        if ($request->filled('from_date')) {
            $query->whereDate('issued_at', '>=', $request->from_date);
        }
        if ($request->filled('to_date')) {
            $query->whereDate('issued_at', '<=', $request->to_date);
        }

        $issues = $query->latest('issued_at')->paginate(20)->withQueryString();
        $items = InventoryItem::where('hotel_id', $hotelId)->orderBy('name')->get(['id', 'name']);

        return view('inventory.issues', compact('issues', 'items'));
    }

    /**
     * Generate inventory report
     */
    public function report(Request $request)
    {
        $items = InventoryItem::where('hotel_id', $this->getHotelId())->get();
        
        return view('inventory.report', compact('items'));
    }

    /**
     * Show inventory transactions
     */
    public function transactions(Request $request)
    {
        $hotelId = $this->getHotelId();
        $query = InventoryMovement::where('hotel_id', $hotelId)->with(['item:id,name', 'performer:id,first_name,last_name']);
        if ($request->filled('type')) {
            $query->where('movement_type', $request->type);
        }
        if ($request->filled('date_from')) {
            $query->whereDate('performed_at', '>=', $request->date_from);
        }
        if ($request->filled('date_to')) {
            $query->whereDate('performed_at', '<=', $request->date_to);
        }
        $transactions = $query->orderByDesc('created_at')->paginate(20)->withQueryString();

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

    /**
     * Show item transactions
     */
    public function itemTransactions($item)
    {
        $hotelId = $this->getHotelId();
        $item = InventoryItem::where('hotel_id', $hotelId)->findOrFail($item);
        $transactions = InventoryMovement::where('hotel_id', $hotelId)
            ->where('inventory_item_id', $item->id)
            ->with('performer:id,first_name,last_name')
            ->orderByDesc('created_at')
            ->get();
        
        return view('inventory.item-transactions', compact('item', 'transactions'));
    }

    private function logMovement(
        int $hotelId,
        InventoryItem $item,
        string $type,
        int $before,
        int $change,
        int $after,
        ?string $reference = null,
        ?string $reason = null,
        ?string $notes = null
    ): void {
        InventoryMovement::create([
            'hotel_id' => $hotelId,
            'inventory_item_id' => $item->id,
            'movement_type' => $type,
            'source_type' => 'inventory',
            'source_id' => null,
            'quantity_before' => $before,
            'quantity_change' => $change,
            'quantity_after' => $after,
            'reference_number' => $reference,
            'reason' => $reason,
            'notes' => $notes,
            'performed_by' => auth()->id(),
            'performed_at' => now(),
        ]);
    }

    /**
     * Toggle item status
     */
    public function toggleStatus(InventoryItem $inventoryItem)
    {
        // Check if active column exists
        if (Schema::hasColumn('inventory_items', 'active')) {
            $inventoryItem->update([
                'active' => !$inventoryItem->active
            ]);
            
            $status = $inventoryItem->active ? 'activated' : 'deactivated';
            
            return redirect()->route('inventory.index')
                             ->with('success', "Item $status successfully.");
        }
        
        return redirect()->route('inventory.index')
                         ->with('error', 'Active status feature not available.');
    }

    /**
     * Get item details for modal
     */
    public function getItemDetails($id)
    {
        $item = InventoryItem::where('hotel_id', $this->getHotelId())->findOrFail($id);
        // This endpoint is consumed by fetch() from the inventory table edit action.
        // Always return the modal partial to avoid non-AJAX fallback mismatches.
        return view('inventory.partials.item-details', compact('item'));
    }

    /**
     * API: Get low stock count
     */
    public function getLowStockCount()
    {
        $hotelId = $this->getHotelId();
        $count = InventoryItem::where('hotel_id', $hotelId)
                             ->whereColumn('quantity', '<=', 'min_stock')
                             ->where('quantity', '>', 0)
                             ->count();
        
        return response()->json(['count' => $count]);
    }

    /**
     * Backward-compatible alias for routes using lowStockCount.
     */
    public function lowStockCount()
    {
        return $this->getLowStockCount();
    }

    /**
     * API: Get categories
     */
    public function getCategories()
    {
        // Return a simple list of category strings.
        $categories = InventoryItem::where('hotel_id', $this->getHotelId())->select('category')->distinct()->pluck('category');
        return response()->json(['categories' => $categories]);
    }

    public function exportPdf(Request $request)
    {
        $items = InventoryItem::where('hotel_id', $this->getHotelId())->get();
        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('inventory.pdf', compact('items'));
        return $pdf->download('inventory-report-' . date('Y-m-d') . '.pdf');
    }

    public function exportCsv(Request $request)
    {
        $items = InventoryItem::where('hotel_id', $this->getHotelId())->get();
        $filename = "inventory-report-" . date('Y-m-d') . ".csv";

        $headers = [
            "Content-type"        => "text/csv",
            "Content-Disposition" => "attachment; filename=$filename",
            "Pragma"              => "no-cache",
            "Cache-Control"       => "must-revalidate, post-check=0, pre-check=0",
            "Expires"             => "0"
        ];

        $columns = ['Item Name', 'Category', 'Quantity', 'Min Stock', 'Unit Price', 'Supplier'];

        $callback = function() use($items, $columns) {
            $file = fopen('php://output', 'w');
            fputcsv($file, $columns);

            foreach ($items as $item) {
                // Safely handle relations if they are strings or objects
                $category = is_object($item->category) ? ($item->category->name ?? '') : $item->category;
                $supplier = is_object($item->supplier) ? ($item->supplier->company ?? '') : $item->supplier;
                
                fputcsv($file, [
                    $item->name, 
                    $category, 
                    $item->quantity, 
                    $item->min_stock, 
                    $item->unit_price, 
                    $supplier
                ]);
            }

            fclose($file);
        };

        return response()->stream($callback, 200, $headers);
    }

    public function exportExcel(Request $request)
    {
        return $this->exportCsv($request);
    }
}