<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Inventory;
use App\Models\Product;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Illuminate\View\View;

class InventoryController extends Controller
{
    public function index(Request $request): View|JsonResponse
    {
        // Handle AJAX requests for inventory items
        if ($request->ajax() || $request->has('ajax')) {
            return $this->getInventoryItems($request);
        }

        // Calculate stats
        try {
            // Total number of inventory records (not sum of quantities)
            $totalItems = Inventory::count();
        } catch (\Exception $e) {
            $totalItems = 0;
        }

        $lowStock = Product::where('type', 'product')
            ->whereColumn('stock', '<=', 'alert_quantity')
            ->where('stock', '>', 0)
            ->count();
        $outOfStock = Product::where('type', 'product')
            ->where('stock', '<=', 0)
            ->count();

        try {
            $totalValue = Product::where('type', 'product')
                ->sum(DB::raw('stock * purchase_price')) ?? 0;
        } catch (\Exception $e) {
            $totalValue = 0;
        }

        // Get inventory items
        try {
            $inventoryItems = Inventory::with(['product.category', 'product.brand', 'product.unit'])
                ->latest()
                ->paginate(10);
        } catch (\Exception $e) {
            $inventoryItems = collect([]);
        }

        return view('admin.inventory.index', compact('inventoryItems', 'totalItems', 'lowStock', 'outOfStock', 'totalValue'));
    }

    private function getInventoryItems(Request $request): JsonResponse
    {
        try {
            // Check if inventories table exists
            if (! Schema::hasTable('inventories')) {
                return response()->json([
                    'success' => true,
                    'data' => [],
                    'pagination' => [
                        'current_page' => 1,
                        'last_page' => 1,
                        'per_page' => 10,
                        'total' => 0,
                    ],
                ]);
            }

            $query = Inventory::with(['product.category', 'product.brand', 'product.unit']);

            // Search functionality - search in product name/code and inventory code
            if ($request->has('search') && ! empty($request->search)) {
                $search = $request->search;
                $query->where(function ($q) use ($search) {
                    $q->where('code', 'like', "%{$search}%")
                        ->orWhere('unit', 'like', "%{$search}%")
                        ->orWhereHas('product', function ($productQuery) use ($search) {
                            $productQuery->where('name', 'like', "%{$search}%")
                                ->orWhere('code', 'like', "%{$search}%");
                        });
                });
            }

            $perPage = $request->get('per_page', 10);
            $inventoryItems = $query->latest()->paginate($perPage);

            return response()->json([
                'success' => true,
                'data' => $inventoryItems->items(),
                'pagination' => [
                    'current_page' => $inventoryItems->currentPage(),
                    'last_page' => $inventoryItems->lastPage(),
                    'per_page' => $inventoryItems->perPage(),
                    'total' => $inventoryItems->total(),
                ],
                'stats' => [
                    'total_items' => Inventory::count(),
                ],
            ]);
        } catch (\Exception $e) {
            Log::error('Error fetching inventory items: '.$e->getMessage());

            return response()->json([
                'success' => false,
                'message' => 'Error fetching inventory items: '.$e->getMessage(),
                'data' => [],
                'pagination' => [
                    'current_page' => 1,
                    'last_page' => 1,
                    'per_page' => 10,
                    'total' => 0,
                ],
            ], 500);
        }
    }

    public function show($id): JsonResponse
    {
        try {
            $inventory = Inventory::with(['product.category', 'product.brand', 'product.unit'])
                ->findOrFail($id);

            return response()->json([
                'success' => true,
                'inventory' => $inventory,
            ]);
        } catch (\Exception $e) {
            Log::error('Error fetching inventory item: '.$e->getMessage());

            return response()->json([
                'success' => false,
                'message' => 'Error fetching inventory item: '.$e->getMessage(),
            ], 404);
        }
    }

    public function getProducts(Request $request): JsonResponse
    {
        try {
            // Start query - Product model uses SoftDeletes, so we get non-deleted products by default
            $query = Product::with(['category', 'brand', 'unit']);

            // Search functionality - search in name or code
            $search = $request->get('search', '');
            if (! empty($search) && trim($search) !== '') {
                $query->where(function ($q) use ($search) {
                    $q->where('name', 'like', "%{$search}%")
                        ->orWhere('code', 'like', "%{$search}%");
                });
            }

            // Get total count for pagination (before limit)
            $total = $query->count();

            // Limit results and order
            $products = $query->orderBy('name', 'asc')->limit(50)->get();

            // Log for debugging
            Log::info('Inventory getProducts called', [
                'search' => $search,
                'total' => $total,
                'products_count' => $products->count(),
            ]);

            return response()->json([
                'success' => true,
                'products' => $products->map(function ($product) {
                    return [
                        'id' => $product->id,
                        'text' => $product->name.' ('.($product->code ?? 'N/A').')',
                        'name' => $product->name,
                        'code' => $product->code ?? '',
                        'unit' => $product->unit ? $product->unit->short_name : '',
                        'purchase_price' => $product->purchase_price ?? 0,
                        'selling_price' => $product->selling_price ?? 0,
                        'type' => $product->type ?? 'product',
                    ];
                })->toArray(),
                'total' => $total,
            ]);
        } catch (\Exception $e) {
            Log::error('Error fetching products for inventory: '.$e->getMessage(), [
                'trace' => $e->getTraceAsString(),
                'request' => $request->all(),
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Error fetching products: '.$e->getMessage(),
                'products' => [],
                'total' => 0,
            ], 500);
        }
    }

    public function store(Request $request): JsonResponse
    {
        // Check if inventories table exists
        if (! Schema::hasTable('inventories')) {
            Log::error('Inventories table does not exist');

            return response()->json([
                'success' => false,
                'message' => 'Inventories table does not exist. Please run migrations: php artisan migrate',
            ], 500);
        }

        $validated = $request->validate([
            'product_id' => 'required|exists:products,id',
            'code' => 'nullable|string|max:255',
            'unit' => 'nullable|string|max:255',
            'purchase_price' => 'nullable|numeric|min:0',
            'selling_price' => 'nullable|numeric|min:0',
            'type' => 'required|in:stock_in,stock_out',
            'quantity' => 'required|integer|min:1',
            'notes' => 'nullable|string',
        ]);

        try {
            $product = Product::findOrFail($validated['product_id']);

            // Auto-fill code and unit if not provided
            if (empty($validated['code'])) {
                $validated['code'] = $product->code;
            }
            if (empty($validated['unit']) && $product->unit) {
                $validated['unit'] = $product->unit->short_name;
            }
            if (empty($validated['purchase_price'])) {
                $validated['purchase_price'] = $product->purchase_price;
            }
            if (empty($validated['selling_price'])) {
                $validated['selling_price'] = $product->selling_price;
            }

            $validated['created_by'] = Auth::id();

            $inventory = Inventory::create($validated);

            // Update product stock based on type
            if ($validated['type'] === 'stock_in') {
                $product->increment('stock', $validated['quantity']);
            } else {
                $product->decrement('stock', $validated['quantity']);
                // Ensure stock doesn't go below 0
                if ($product->stock < 0) {
                    $product->stock = 0;
                    $product->save();
                }
            }

            return response()->json([
                'success' => true,
                'message' => 'Inventory item added successfully',
                'inventory' => $inventory->load(['product.category', 'product.brand', 'product.unit']),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error creating inventory item: '.$e->getMessage(),
            ], 500);
        }
    }

    public function update(Request $request, $id): JsonResponse
    {
        $validated = $request->validate([
            'product_id' => 'required|exists:products,id',
            'code' => 'nullable|string|max:255',
            'unit' => 'nullable|string|max:255',
            'purchase_price' => 'nullable|numeric|min:0',
            'selling_price' => 'nullable|numeric|min:0',
            'type' => 'required|in:stock_in,stock_out',
            'quantity' => 'required|integer|min:1',
            'notes' => 'nullable|string',
        ]);

        try {
            $inventory = Inventory::findOrFail($id);
            $oldQuantity = $inventory->quantity;
            $oldType = $inventory->type;
            $product = Product::findOrFail($validated['product_id']);

            // Revert old stock change
            if ($oldType === 'stock_in') {
                $product->decrement('stock', $oldQuantity);
            } else {
                $product->increment('stock', $oldQuantity);
            }

            // Apply new stock change
            if ($validated['type'] === 'stock_in') {
                $product->increment('stock', $validated['quantity']);
            } else {
                $product->decrement('stock', $validated['quantity']);
                if ($product->stock < 0) {
                    $product->stock = 0;
                    $product->save();
                }
            }

            $inventory->update($validated);

            return response()->json([
                'success' => true,
                'message' => 'Inventory item updated successfully',
                'inventory' => $inventory->load(['product.category', 'product.brand', 'product.unit']),
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error updating inventory item: '.$e->getMessage(),
            ], 500);
        }
    }

    public function destroy($id): JsonResponse
    {
        try {
            $inventory = Inventory::findOrFail($id);
            $product = $inventory->product;

            // Revert stock change
            if ($inventory->type === 'stock_in') {
                $product->decrement('stock', $inventory->quantity);
            } else {
                $product->increment('stock', $inventory->quantity);
            }

            $inventory->delete();

            return response()->json([
                'success' => true,
                'message' => 'Inventory item deleted successfully',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error deleting inventory item: '.$e->getMessage(),
            ], 500);
        }
    }
}
