<?php

namespace App\Http\Controllers;

use App\Models\Inventory;
use App\Models\InventoryCategory;
use App\Models\InventoryTransaction;
use App\Models\Supplier;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use App\Exports\InventoryExport;
use Maatwebsite\Excel\Facades\Excel;

class InventoryController extends Controller
{
    /**
     * Display a listing of the inventory items.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $query = Inventory::query();
        
        // Aplicar filtros si existen
        if ($request->has('category_id') && $request->category_id) {
            $query->where('category_id', $request->category_id);
        }
        
        if ($request->has('search') && $request->search) {
            $search = $request->search;
            $query->where(function($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                  ->orWhere('description', 'like', "%{$search}%")
                  ->orWhere('serial_number', 'like', "%{$search}%")
                  ->orWhere('brand', 'like', "%{$search}%")
                  ->orWhere('model', 'like', "%{$search}%");
            });
        }
        
        if ($request->has('status') && $request->status) {
            $query->where('status', $request->status);
        }
        
        // Aplicar ordenamiento
        $orderBy = $request->input('order_by', 'name');
        $orderDir = $request->input('order_dir', 'asc');
        $query->orderBy($orderBy, $orderDir);
        
        // Obtener los items paginados
        $inventoryItems = $query->with('category', 'supplier')->paginate(15);
        
        // Obtener categorías para el filtro
        $categories = InventoryCategory::getActive();
        
        return view('admin.inventory.index', compact('inventoryItems', 'categories'));
    }

    /**
     * Show the form for creating a new inventory item.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $categories = InventoryCategory::getActive();
        $suppliers = Supplier::getActive();
        
        return view('admin.inventory.create', compact('categories', 'suppliers'));
    }

    /**
     * Store a newly created inventory item in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'category_id' => 'required|exists:inventory_categories,id',
            'quantity' => 'required|numeric|min:0',
            'min_stock' => 'nullable|numeric|min:0',
            'unit_price' => 'nullable|numeric|min:0',
            'expiration_date' => 'nullable|date',
            'location' => 'nullable|string|max:255',
            'status' => 'required|string|in:active,inactive,maintenance',
            'serial_number' => 'nullable|string|max:255',
            'brand' => 'nullable|string|max:255',
            'model' => 'nullable|string|max:255',
            'supplier_id' => 'nullable|exists:suppliers,id',
            'last_maintenance' => 'nullable|date',
            'next_maintenance' => 'nullable|date',
            'image' => 'nullable|image|max:2048',
            'notes' => 'nullable|string',
        ]);
        
        // Manejar carga de imagen si existe
        if ($request->hasFile('image')) {
            $image = $request->file('image');
            $imageName = time() . '_' . Str::slug($request->name) . '.' . $image->getClientOriginalExtension();
            $image->storeAs('public/inventory', $imageName);
            $validatedData['image_path'] = $imageName;
        }
        
        // Crear el ítem de inventario
        $inventoryItem = Inventory::create($validatedData);
        
        // Registrar la transacción inicial
        InventoryTransaction::create([
            'inventory_id' => $inventoryItem->id,
            'user_id' => Auth::id(),
            'transaction_type' => InventoryTransaction::TYPE_ENTRY,
            'quantity' => $validatedData['quantity'],
            'previous_quantity' => 0,
            'new_quantity' => $validatedData['quantity'],
            'reference' => 'Inventario inicial',
            'notes' => 'Creación del ítem de inventario',
        ]);
        
        return redirect()->route('inventory.index')
            ->with('success', 'Ítem de inventario creado exitosamente.');
    }

    /**
     * Display the specified inventory item.
     *
     * @param  \App\Models\Inventory  $inventory
     * @return \Illuminate\Http\Response
     */
    public function show(Inventory $inventory)
    {
        // Cargar las relaciones
        $inventory->load('category', 'supplier');
        
        // Obtener las últimas 10 transacciones
        $transactions = $inventory->transactions()
            ->with('user')
            ->orderBy('created_at', 'desc')
            ->take(10)
            ->get();
            
        return view('admin.inventory.show', compact('inventory', 'transactions'));
    }

    /**
     * Show the form for editing the specified inventory item.
     *
     * @param  \App\Models\Inventory  $inventory
     * @return \Illuminate\Http\Response
     */
    public function edit(Inventory $inventory)
    {
        $categories = InventoryCategory::getActive();
        $suppliers = Supplier::getActive();
        
        return view('admin.inventory.edit', compact('inventory', 'categories', 'suppliers'));
    }

    /**
     * Update the specified inventory item in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Inventory  $inventory
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Inventory $inventory)
    {
        $validatedData = $request->validate([
            'name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'category_id' => 'required|exists:inventory_categories,id',
            'min_stock' => 'nullable|numeric|min:0',
            'unit_price' => 'nullable|numeric|min:0',
            'expiration_date' => 'nullable|date',
            'location' => 'nullable|string|max:255',
            'status' => 'required|string|in:active,inactive,maintenance',
            'serial_number' => 'nullable|string|max:255',
            'brand' => 'nullable|string|max:255',
            'model' => 'nullable|string|max:255',
            'supplier_id' => 'nullable|exists:suppliers,id',
            'last_maintenance' => 'nullable|date',
            'next_maintenance' => 'nullable|date',
            'image' => 'nullable|image|max:2048',
            'notes' => 'nullable|string',
        ]);
        
        // Manejar carga de imagen si existe
        if ($request->hasFile('image')) {
            // Eliminar imagen anterior si existe
            if ($inventory->image_path) {
                Storage::delete('public/inventory/' . $inventory->image_path);
            }
            
            $image = $request->file('image');
            $imageName = time() . '_' . Str::slug($request->name) . '.' . $image->getClientOriginalExtension();
            $image->storeAs('public/inventory', $imageName);
            $validatedData['image_path'] = $imageName;
        }
        
        // Si se está cambiando la cantidad, registrar una transacción
        if ($request->has('quantity') && $request->quantity != $inventory->quantity) {
            $previousQuantity = $inventory->quantity;
            $newQuantity = $request->quantity;
            $difference = $newQuantity - $previousQuantity;
            
            $transactionType = $difference > 0 
                ? InventoryTransaction::TYPE_ENTRY 
                : InventoryTransaction::TYPE_EXIT;
            
            InventoryTransaction::create([
                'inventory_id' => $inventory->id,
                'user_id' => Auth::id(),
                'transaction_type' => $transactionType,
                'quantity' => abs($difference),
                'previous_quantity' => $previousQuantity,
                'new_quantity' => $newQuantity,
                'reference' => 'Ajuste manual',
                'notes' => $request->notes ?? 'Actualización de cantidad en inventario',
            ]);
            
            $inventory->quantity = $newQuantity;
        }
        
        // Actualizar el ítem de inventario
        $inventory->update($validatedData);
        
        return redirect()->route('inventory.index')
            ->with('success', 'Ítem de inventario actualizado exitosamente.');
    }

    /**
     * Remove the specified inventory item from storage.
     *
     * @param  \App\Models\Inventory  $inventory
     * @return \Illuminate\Http\Response
     */
    public function destroy(Inventory $inventory)
    {
        // Eliminar imagen si existe
        if ($inventory->image_path) {
            Storage::delete('public/inventory/' . $inventory->image_path);
        }
        
        // Eliminar el ítem de inventario (soft delete)
        $inventory->delete();
        
        return redirect()->route('inventory.index')
            ->with('success', 'Ítem de inventario eliminado exitosamente.');
    }

    /**
     * Adjust the inventory item quantity.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Inventory  $inventory
     * @return \Illuminate\Http\Response
     */
    public function adjustQuantity(Request $request, Inventory $inventory)
    {
        $validatedData = $request->validate([
            'quantity' => 'required|numeric',
            'transaction_type' => 'required|in:entry,exit,adjustment',
            'notes' => 'nullable|string',
        ]);
        
        $previousQuantity = $inventory->quantity;
        $quantity = abs($validatedData['quantity']);
        
        if ($validatedData['transaction_type'] == InventoryTransaction::TYPE_ENTRY) {
            $newQuantity = $previousQuantity + $quantity;
        } elseif ($validatedData['transaction_type'] == InventoryTransaction::TYPE_EXIT) {
            if ($quantity > $previousQuantity) {
                return back()->with('error', 'No hay suficiente stock para realizar esta salida.');
            }
            $newQuantity = $previousQuantity - $quantity;
        } else { // adjustment
            $newQuantity = $quantity;
        }
        
        // Registrar la transacción
        InventoryTransaction::create([
            'inventory_id' => $inventory->id,
            'user_id' => Auth::id(),
            'transaction_type' => $validatedData['transaction_type'],
            'quantity' => $quantity,
            'previous_quantity' => $previousQuantity,
            'new_quantity' => $newQuantity,
            'reference' => 'Ajuste manual',
            'notes' => $validatedData['notes'] ?? 'Ajuste de cantidad',
        ]);
        
        // Actualizar la cantidad en el inventario
        $inventory->quantity = $newQuantity;
        $inventory->save();
        
        return back()->with('success', 'Cantidad ajustada exitosamente.');
    }

    /**
     * Show low stock inventory items.
     *
     * @return \Illuminate\Http\Response
     */
    public function lowStock()
    {
        $lowStockItems = Inventory::whereRaw('quantity <= min_stock')
            ->where('min_stock', '>', 0)
            ->with('category', 'supplier')
            ->paginate(15);
            
        return view('admin.inventory.low_stock', compact('lowStockItems'));
    }

    /**
     * Show inventory items by category.
     *
     * @param  \App\Models\InventoryCategory  $category
     * @return \Illuminate\Http\Response
     */
    public function byCategory(InventoryCategory $category)
    {
        $inventoryItems = Inventory::where('category_id', $category->id)
            ->with('supplier')
            ->paginate(15);
            
        return view('admin.inventory.by_category', compact('inventoryItems', 'category'));
    }

    /**
     * Export inventory as Excel.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function export(Request $request)
    {
        return Excel::download(new InventoryExport, 'inventario_' . date('Y-m-d') . '.xlsx');
    }
} 