<?php

namespace App\Http\Controllers;

use App\Exports\ProduitsExport;
use App\Models\Fournisseur;
use App\Models\Magasin;
use App\Models\Mouvement;
use App\Models\Produit;
use App\Models\Stock;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Maatwebsite\Excel\Facades\Excel;

/**
 * Contrôleur des produits.
 * Gère les opérations CRUD avec fournisseur et stock initial.
 */
class ProduitController extends Controller
{
    /**
     * Redirige vers l'index (formulaire géré en modal sur la page liste).
     */
    public function create()
    {
        return redirect()->route('produits.index');
    }

    /**
     * Redirige vers l'index (édition gérée en modal sur la page liste).
     */
    public function edit(string $id)
    {
        return redirect()->route('produits.index');
    }

    /**
     * Liste les produits avec pagination et filtres (fournisseur, produit).
     */
    public function index(Request $request)
    {
        $query = Produit::with(['fournisseur', 'stock.magasin'])->latest();

        if ($request->filled('fournisseur_id')) {
            $query->where('fournisseur_id', $request->fournisseur_id);
        }

        if ($request->filled('produit_id')) {
            $query->where('id', $request->produit_id);
        }

        $produits = $query->paginate(10)->withQueryString();

        $fournisseurs = Fournisseur::whereNull('deleted_at')->orderBy('nom')->get();
        $magasins = Magasin::where('disabled', false)->orderBy('nom')->get();
        $produitsFiltre = Produit::orderBy('designation')->get(['id', 'designation', 'reference']);

        return view('produits.index', compact('produits', 'fournisseurs', 'magasins', 'produitsFiltre'));
    }

    /**
     * Exporte les produits en Excel selon les filtres appliqués.
     */
    public function export(Request $request)
    {
        $query = Produit::with(['fournisseur', 'stock.magasin'])->latest();

        if ($request->filled('fournisseur_id')) {
            $query->where('fournisseur_id', $request->fournisseur_id);
        }

        if ($request->filled('produit_id')) {
            $query->where('id', $request->produit_id);
        }

        $produits = $query->get();

        $filename = 'produits';
        if ($request->filled('fournisseur_id')) {
            $fournisseur = Fournisseur::find($request->fournisseur_id);
            $filename .= '_' . ($fournisseur ? Str::slug($fournisseur->nom) : $request->fournisseur_id);
        }
        if ($request->filled('produit_id')) {
            $produit = Produit::find($request->produit_id);
            $filename .= '_' . ($produit ? Str::slug($produit->designation) : $request->produit_id);
        }
        $filename .= '_' . now()->format('Y-m-d_H-i') . '.xlsx';

        return Excel::download(new ProduitsExport($produits), $filename);
    }

    /**
     * Crée un nouveau produit avec son stock initial.
     * Enregistre également un mouvement de type "stock_initial" pour tracer l'entrée.
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'designation' => 'required|string|max:255',
            'fournisseur_id' => 'nullable|exists:fournisseurs,id',
            'prix' => 'required|numeric|min:0',
            'prix_vente' => 'required|numeric|min:0',
            'unite' => 'nullable|string|max:20',
            'magasin_id' => 'required|exists:magasins,id',
            'quantite' => 'required|integer|min:1',
            'seuil_alerte' => 'required|integer|min:5',
        ]);

        // Création du produit (infos générales : désignation, prix, fournisseur, etc.)
        $produit = Produit::create([
            'designation' => $validated['designation'],
            'fournisseur_id' => $validated['fournisseur_id'] ?? null,
            'prix' => $validated['prix'],
            'prix_vente' => $validated['prix_vente'],
            'unite' => $validated['unite'] ?: null,
        ]);

        // Création du stock initial dans le magasin sélectionné
        Stock::create([
            'magasin_id' => $validated['magasin_id'],
            'produit_id' => $produit->id,
            'quantite' => $validated['quantite'],
            'seuil_alerte' => $validated['seuil_alerte'],
        ]);

        // Traçabilité : enregistrer un mouvement pour l'entrée initiale en stock
        if ($validated['quantite'] > 0) {
            Mouvement::create([
                'type' => Mouvement::TYPE_ENTREE,
                'magasin_id' => $validated['magasin_id'],
                'produit_id' => $produit->id,
                'quantite' => $validated['quantite'],
            ]);
        }

        return redirect()->route('produits.index')->with('success', 'Produit créé avec succès');
    }

    /**
     * Met à jour un produit existant.
     * Si des données de stock sont fournies, met à jour le stock et crée un mouvement
     * (entrée ou sortie) selon la variation de quantité.
     */
    public function update(Request $request, string $id)
    {
        $validated = $request->validate([
            'designation' => 'required|string|max:255',
            'fournisseur_id' => 'nullable|exists:fournisseurs,id',
            'prix' => 'required|numeric|min:0',
            'prix_vente' => 'required|numeric|min:0',
            'unite' => 'nullable|string|max:20',
            'magasin_id' => 'nullable|exists:magasins,id',
            'quantite' => 'nullable|integer|min:0',
            'seuil_alerte' => 'nullable|integer|min:0',
        ]);

        $produit = Produit::findOrFail(Produit::keyFromHashId($id));

        // Mise à jour des infos générales du produit
        $produit->update([
            'designation' => $validated['designation'],
            'fournisseur_id' => $validated['fournisseur_id'] ?? null,
            'prix' => $validated['prix'],
            'prix_vente' => $validated['prix_vente'],
            'unite' => $validated['unite'] ?: null,
        ]);

        // Traitement du stock uniquement si magasin, quantité et seuil sont renseignés
        $hasStockData = $request->filled('magasin_id')
            && $request->filled('quantite') !== null
            && $request->filled('seuil_alerte') !== null;
        if ($hasStockData) {
            // Récupère le stock existant ou en crée un nouveau pour ce magasin/produit
            $stock = Stock::firstOrNew([
                'magasin_id' => $validated['magasin_id'],
                'produit_id' => $produit->id,
            ]);

            // Mémorise l'ancienne quantité avant modification (0 si nouveau stock)
            $ancienneQuantite = $stock->exists ? $stock->quantite : 0;

            // Met à jour le stock
            $stock->quantite = $validated['quantite'];
            $stock->seuil_alerte = $validated['seuil_alerte'];
            $stock->save();

            // Calcule la variation pour créer le mouvement approprié
            $diff = $validated['quantite'] - $ancienneQuantite;
            if ($diff > 0) {
                // Augmentation : mouvement d'entrée (ex: 10 → 25 = entrée de 15)
                Mouvement::create([
                    'type' => Mouvement::TYPE_ENTREE,
                    'magasin_id' => $validated['magasin_id'],
                    'produit_id' => $produit->id,
                    'quantite' => $diff,

                ]);
            } elseif ($diff < 0) {
                // Diminution : mouvement de sortie (ex: 25 → 10 = sortie de 15)
                Mouvement::create([
                    'type' => Mouvement::TYPE_SORTIE,
                    'magasin_id' => $validated['magasin_id'],
                    'produit_id' => $produit->id,
                    'quantite' => $diff,
                ]);
            }
            // Si $diff == 0 : aucune variation, pas de mouvement créé
        }

        return redirect()->route('produits.index')->with('success', 'Produit mis à jour avec succès');
    }

    /**
     * Supprime un produit (soft delete).
     */
    public function destroy(string $id)
    {
        $produit = Produit::findOrFail(Produit::keyFromHashId($id));
        $produit->delete();
        return redirect()->route('produits.index')->with('success', 'Produit supprimé avec succès');
    }
}
