<?php

namespace App\Http\Controllers;

use App\Exports\DepensesExport;
use App\Models\Depense;
use App\Models\Magasin;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Maatwebsite\Excel\Facades\Excel;

/**
 * Contrôleur des dépenses.
 * Gère les opérations CRUD, les filtres par mois/année et l'export XLSX.
 */
class DepenseController extends Controller
{
    /**
     * Affiche la liste des dépenses avec filtres optionnels.
     *
     * @param Request $request Paramètres GET : annee, mois, magasin_id
     * @return \Illuminate\View\View
     */
    public function index(Request $request)
    {
        // Requête de base : dépenses avec magasin associé, triées par date décroissante
        $query = Depense::with('magasin')->latest();

        $isSqlite = DB::connection()->getDriverName() === 'sqlite';

        // Filtre par magasin si fourni
        if ($request->filled('magasin_id')) {
            $query->where('magasin_id', $request->magasin_id);
        }
        // Filtre par année si fourni (compatible SQLite et MySQL)
        if ($request->filled('annee')) {
            $yearSql = $isSqlite ? "strftime('%Y', date_depense) = ?" : 'YEAR(date_depense) = ?';
            $query->whereRaw($yearSql, [$request->annee]);
        }
        // Filtre par mois si fourni
        if ($request->filled('mois')) {
            $monthSql = $isSqlite ? "strftime('%m', date_depense) = ?" : 'MONTH(date_depense) = ?';
            $query->whereRaw($monthSql, [$request->mois]);
        }

        // Pagination (10 par page) en conservant les paramètres de filtre dans l'URL
        $depenses = $query->paginate(10)->withQueryString();

        // Magasins actifs pour le formulaire d'ajout
        $magasins = Magasin::where('disabled', false)->orderBy('nom')->get();
        // Tous les magasins pour le filtre (y compris désactivés, pour les données historiques)
        $magasinsFiltre = Magasin::orderBy('nom')->get();

        // Liste des années disponibles (compatible SQLite : strftime, MySQL : YEAR)
        $yearSelect = $isSqlite ? "strftime('%Y', date_depense) as annee" : 'YEAR(date_depense) as annee';
        $annees = Depense::selectRaw($yearSelect)
            ->distinct()
            ->orderByDesc('annee')
            ->pluck('annee');

        // Fallback : année courante si aucune dépense en base
        if ($annees->isEmpty()) {
            $annees = collect([now()->year]);
        }

        return view('depenses.index', compact('depenses', 'magasins', 'magasinsFiltre', 'annees'));
    }

    /**
     * Exporte les dépenses en XLSX selon les filtres appliqués.
     *
     * @param Request $request Paramètres GET : annee, mois (mêmes filtres que index)
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function export(Request $request)
    {
        $isSqlite = DB::connection()->getDriverName() === 'sqlite';

        // Même logique de filtrage que la liste
        $query = Depense::with('magasin')->latest();

        if ($request->filled('magasin_id')) {
            $query->where('magasin_id', $request->magasin_id);
        }
        if ($request->filled('annee')) {
            $yearSql = $isSqlite ? "strftime('%Y', date_depense) = ?" : 'YEAR(date_depense) = ?';
            $query->whereRaw($yearSql, [$request->annee]);
        }
        if ($request->filled('mois')) {
            $monthSql = $isSqlite ? "strftime('%m', date_depense) = ?" : 'MONTH(date_depense) = ?';
            $query->whereRaw($monthSql, [$request->mois]);
        }

        $depenses = $query->get();

        // Construction du nom du fichier : depenses_MagasinPrincipal_2026_Janvier_2026-02-25_15-30.xlsx
        $filename = 'depenses';
        if ($request->filled('magasin_id')) {
            $magasin = Magasin::find($request->magasin_id);
            $slug = $magasin ? Str::slug($magasin->nom) : $request->magasin_id;
            $filename .= '_' . $slug;
        }
        if ($request->filled('annee')) {
            $filename .= '_' . $request->annee;
            if ($request->filled('mois')) {
                $moisNoms = [
                    '',
                    'Janvier',
                    'Février',
                    'Mars',
                    'Avril',
                    'Mai',
                    'Juin',
                    'Juillet',
                    'Août',
                    'Septembre',
                    'Octobre',
                    'Novembre',
                    'Décembre'
                ];
                $filename .= '_' . ($moisNoms[(int) $request->mois] ?? $request->mois);
            }
        }
        $filename .= '_' . now()->format('Y-m-d_H-i') . '.xlsx';

        return Excel::download(new DepensesExport($depenses), $filename);
    }

    /**
     * Enregistre une nouvelle dépense.
     *
     * @param Request $request libelle, magasin_id, montant, date_depense
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'libelle' => 'required|string|max:255',
            'magasin_id' => 'required|exists:magasins,id',
            'montant' => 'required|numeric|min:0',
            'date_depense' => 'required|date',
        ]);
        Depense::create($validated);
        return redirect()->route('depenses.index')->with('success', 'Dépense créée avec succès');
    }

    /**
     * Met à jour une dépense existante.
     *
     * @param Request $request libelle, magasin_id, montant, date_depense
     * @param string $id ID de la dépense
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(Request $request, string $id)
    {
        $validated = $request->validate([
            'libelle' => 'required|string|max:255',
            'magasin_id' => 'required|exists:magasins,id',
            'montant' => 'required|numeric|min:0',
            'date_depense' => 'required|date',
        ]);

        $depense = Depense::findOrFail($id);
        $depense->update($validated);

        return redirect()->route('depenses.index')->with('success', 'Dépense mise à jour avec succès');
    }

    /**
     * Supprime une dépense (soft delete).
     *
     * @param string $id ID de la dépense
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy(string $id)
    {
        $depense = Depense::findOrFail(Depense::keyFromHashId($id));

        $depense->update([
            'deleted_at' => now()
        ]);
        return redirect()->route('depenses.index')->with('success', 'Dépense supprimée avec succès');
    }
}