<?php

namespace App\Http\Controllers;

use App\Models\Stock;
use App\Models\Product;
use App\Models\Department;
use App\Services\AuditService;
use Illuminate\Http\Request;
use App\Models\MovementStock;
use App\Exports\MovementsExport;
use App\Models\Request as RequestModel;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;

class MovementStockController extends Controller
{
    /**
     * Page des mouvements avec onglets Entrée / Sortie / Historique
     */
    public function index(Request $request)
    {
        if (!auth()->user()->hasPermissionTo('movement_stocks.view')) {
            abort(403, 'Vous n\'êtes pas autorisé à accéder à cette page.');
        }

        $tab = $request->get('tab', 'sortie');
        $departmentId = $request->get('department_id') ? (int) $request->get('department_id') : null;
        $dateFrom = $request->get('date_from');
        $dateTo = $request->get('date_to');

        // Mouvements enregistrés
        $movementsQuery = MovementStock::with(['product', 'department', 'user', 'request'])
            ->whereDeletedAt(null)
            ->orderBy('created_at', 'desc');

        if ($tab === 'entree') {
            $movementsQuery->where('type', 'entree');
        } elseif ($tab === 'sortie') {
            $movementsQuery->where('type', 'sortie');
        }

        if ($departmentId) {
            $movementsQuery->where('department_id', $departmentId);
        }
        if ($dateFrom) {
            $movementsQuery->whereDate('created_at', '>=', $dateFrom);
        }
        if ($dateTo) {
            $movementsQuery->whereDate('created_at', '<=', $dateTo);
        }

        $movements = $movementsQuery->paginate(15)->withQueryString();

        // Demandes validées non encore exécutées (pour l'onglet Sortie)
        $validatedRequests = collect();
        if ($tab === 'sortie') {
            $validatedRequests = RequestModel::with(['department', 'requestDetails.product'])
                ->where('status', 'validée')
                ->whereDeletedAt(null)
                ->whereDoesntHave('movementStocks')
                ->orderBy('approved_at', 'desc')
                ->get();
        }

        $departments = Department::orderBy('name')->whereDeletedAt(null)->get();
        $products = Product::orderBy('name')->whereDeletedAt(null)->where('status', 'actif')->get();

        // Comptes par type pour les badges des onglets (sans filtres)
        $countEntree = MovementStock::whereDeletedAt(null)->where('type', 'entree')->count();
        $countSortie = MovementStock::whereDeletedAt(null)->where('type', 'sortie')->count();

        return view('movements.index', compact('movements', 'validatedRequests', 'departments', 'products', 'tab', 'countEntree', 'countSortie', 'departmentId', 'dateFrom', 'dateTo'));
    }

    /**
     * Enregistrer une entrée de stock (Magasinier, Super Administrateur uniquement)
     */
    public function storeEntree(Request $request)
    {
        $this->authorize('create', MovementStock::class);

        $validated = $request->validate([
            'product_id' => 'required|exists:products,id',
            'quantity' => 'required|integer|min:1',
            'department_id' => 'required|exists:departments,id',
            'notes' => 'nullable|string|max:500',
        ]);

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

        DB::transaction(function () use ($validated, $product) {
            MovementStock::create([
                'type' => 'entree',
                'quantity' => $validated['quantity'],
                'product_id' => $validated['product_id'],
                'department_id' => $validated['department_id'],
                'user_id' => Auth::id(),
                'notes' => $validated['notes'] ?? null,
            ]);

            $stock = $product->stocks()->first();
            if ($stock) {
                $stock->increment('actual_quantity', $validated['quantity']);
                $stock->increment('quantity_available', $validated['quantity']);
            } else {
                Stock::create([
                    'reference' => 'STK-' . strtoupper(\Illuminate\Support\Str::random(4)),
                    'name' => $product->name,
                    'product_id' => $product->id,
                    'user_id' => Auth::id(),
                    'actual_quantity' => $validated['quantity'],
                    'quantity_available' => $validated['quantity'],
                    'reserved_quantity' => 0,
                ]);
            }
        });

        $deptName = Department::find($validated['department_id'])?->name ?? 'N/A';
        AuditService::log('create', 'MovementStock', null, "Entrée de stock: {$product->name} x{$validated['quantity']} - Département {$deptName}");

        return redirect()->route('movements.index', ['tab' => 'entree'])
            ->with('success', 'Entrée de stock enregistrée avec succès.');
    }

    /**
     * Enregistrer une sortie de stock
     * - Sortie depuis demande validée : movement_stocks.execute_sortie (Contrôleur, Super Admin)
     * - Sortie manuelle : movement_stocks.create (Super Admin uniquement, pas le Magasinier)
     */
    public function storeSortie(Request $request)
    {
        $user = Auth::user();
        if ($request->filled('request_id')) {
            if (!$user->hasPermissionTo('movement_stocks.execute_sortie')) {
                abort(403, 'Vous n\'êtes pas autorisé à exécuter les sorties depuis les demandes validées.');
            }
        } else {
            // Sortie manuelle : create mais pas Magasinier (qui ne peut exécuter aucune sortie)
            if (!$user->hasPermissionTo('movement_stocks.create') || $user->hasRole('Magasinier')) {
                abort(403, 'Vous n\'êtes pas autorisé à effectuer une sortie de stock.');
            }
        }

        $validated = $request->validate([
            'product_id' => 'required|exists:products,id',
            'quantity' => 'required|integer|min:1',
            'department_id' => 'required|exists:departments,id',
            'request_id' => 'nullable|exists:requests,id',
            'notes' => 'nullable|string|max:500',
        ]);

        $product = Product::withSum('stocks as total_stock', 'actual_quantity')->findOrFail($validated['product_id']);
        $stockDisponible = (int) ($product->total_stock ?? 0);

        if ($stockDisponible < $validated['quantity']) {
            return redirect()->back()
                ->withInput()
                ->with('error', "Stock insuffisant. Disponible : {$stockDisponible}, demandé : {$validated['quantity']}.");
        }

        DB::transaction(function () use ($validated) {
            MovementStock::create([
                'type' => 'sortie',
                'quantity' => $validated['quantity'],
                'product_id' => $validated['product_id'],
                'department_id' => $validated['department_id'],
                'user_id' => Auth::id(),
                'request_id' => $validated['request_id'] ?? null,
                'notes' => $validated['notes'] ?? null,
            ]);

            $stock = Product::find($validated['product_id'])->stocks()->first();
            if ($stock) {
                $stock->decrement('actual_quantity', $validated['quantity']);
                $stock->decrement('quantity_available', $validated['quantity']);
            }
        });

        $deptName = Department::find($validated['department_id'])?->name ?? 'N/A';
        AuditService::log('create', 'MovementStock', null, "Sortie de stock: {$product->name} x{$validated['quantity']} - Département {$deptName}");

        return redirect()->route('movements.index', ['tab' => 'sortie'])
            ->with('success', 'Sortie de stock enregistrée avec succès.');
    }

    /**
     * Export des mouvements (avec filtres appliqués)
     */
    public function export(Request $request)
    {
        if (!auth()->user()->hasPermissionTo('movement_stocks.view')) {
            abort(403, 'Vous n\'êtes pas autorisé à exporter les mouvements.');
        }

        $tab = $request->get('tab', 'sortie');
        $departmentId = $request->get('department_id') ? (int) $request->get('department_id') : null;
        $dateFrom = $request->get('date_from');
        $dateTo = $request->get('date_to');

        $export = new MovementsExport($tab, $departmentId, $dateFrom, $dateTo);
        $filename = 'mouvements_' . ($tab ?: 'historique') . '_' . now()->format('Y-m-d_His') . '.xlsx';

        return Excel::download($export, $filename);
    }
}
