<?php

namespace App\Http\Controllers;

use App\Models\Product;
use App\Models\User;
use App\Models\Department;
use Illuminate\Http\Request;
use App\Exports\RequestsExport;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
use App\Models\Request as RequestModel;
use App\Notifications\NewRequestNotification;
use App\Notifications\RequestStatusNotification;
use App\Notifications\ValidatedRequestPendingSortieNotification;

class RequestController extends Controller
{
    /**
     * Liste des demandes
     */

    public function index(Request $request)
    {
        $user = Auth::user();
        $query = RequestModel::orderBy('created_at', 'desc')
            ->with(['user', 'department', 'requestDetails.product'])
            ->whereDeletedAt(null);

        // Responsable du département : uniquement les demandes de son département
        if ($user->hasRole('Responsable du département') && $user->department_id) {
            $query->where('department_id', $user->department_id);
        }
        // Magasinier : uniquement ses propres demandes
        elseif ($user->hasRole('Magasinier')) {
            $query->where('created_by', $user->id);
        }

        // Filtre par statut (onglets)
        if ($status = $request->get('status')) {
            $query->where('status', $status);
        }

        // Filtre par département (sauf pour Responsable)
        if (!$user->hasRole('Responsable du département') && $departmentId = $request->get('department_id')) {
            $query->where('department_id', $departmentId);
        }

        // Filtre par recherche (référence, produit)
        if ($search = $request->get('search')) {
            $query->where(function ($q) use ($search) {
                $q->where('reference', 'like', "%{$search}%")
                    ->orWhereHas('requestDetails.product', fn ($p) => $p->where('name', 'like', "%{$search}%"));
            });
        }

        // Filtre par date
        if ($date = $request->get('date')) {
            $query->whereDate('created_at', $date);
        }

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

        // Comptes par statut (mêmes filtres de base, hors statut)
        $baseQuery = RequestModel::whereDeletedAt(null);
        if ($user->hasRole('Responsable du département') && $user->department_id) {
            $baseQuery->where('department_id', $user->department_id);
        } elseif ($user->hasRole('Magasinier')) {
            $baseQuery->where('created_by', $user->id);
        }
        if (!$user->hasRole('Responsable du département') && $departmentId = $request->get('department_id')) {
            $baseQuery->where('department_id', $departmentId);
        }
        if ($search = $request->get('search')) {
            $baseQuery->where(function ($q) use ($search) {
                $q->where('reference', 'like', "%{$search}%")
                    ->orWhereHas('requestDetails.product', fn ($p) => $p->where('name', 'like', "%{$search}%"));
            });
        }
        if ($date = $request->get('date')) {
            $baseQuery->whereDate('created_at', $date);
        }
        $countEnAttente = (clone $baseQuery)->where('status', 'en_attente')->count();
        $countValidee = (clone $baseQuery)->where('status', 'validée')->count();
        $countRejetee = (clone $baseQuery)->where('status', 'rejetée')->count();

        $departments = $this->getDepartmentsForUser($user);
        $products = Product::latest()->whereDeletedAt(null)->where('status', 'actif')->get();

        return view('requests.index', compact('demandes', 'departments', 'products', 'countEnAttente', 'countValidee', 'countRejetee'));
    }

    /**
     * Retourne les départements visibles pour l'utilisateur (formulaire d'ajout)
     * Responsable du département : uniquement son département
     */
    protected function getDepartmentsForUser($user)
    {
        $baseQuery = Department::latest()->whereDeletedAt(null);

        if ($user->hasRole('Responsable du département') && $user->department_id) {
            return $baseQuery->where('id', $user->department_id)->get();
        }

        return $baseQuery->get();
    }

    /**
     * Enregistrement de la demande
     */
    public function store(Request $request)
    {
        $user = Auth::user();
        $validated = $request->validate([
            'department_id' => 'required|exists:departments,id',
            'product_id' => 'required|exists:products,id',
            'quantity' => 'required|integer|min:1',
            'comments' => 'nullable|string|max:500',
        ]);

        // Responsable du département : ne peut créer que pour son département
        if ($user->hasRole('Responsable du département') && $user->department_id) {
            if ((int) $validated['department_id'] !== (int) $user->department_id) {
                abort(403, 'Vous ne pouvez créer des demandes que pour votre département.');
            }
        }

        // Créer la demande
        $requestModel = RequestModel::create([
            'department_id' => $validated['department_id'],
            'user_id' => Auth::id(),
            'created_by' => Auth::id(),
            'type' => 'Approvisionnement',
            'status' => 'en_attente',
            'comments' => $validated['comments'] ?? null,
        ]);

        // Créer le détail de la demande
        $requestModel->requestDetails()->create([
            'product_id' => $validated['product_id'],
            'quantity' => $validated['quantity'],
        ]);

        // Notifier les utilisateurs pouvant approuver (admin) - sauf le créateur
        $requestModel->load(['department', 'createdBy']);
        $approvers = User::permission('requests.approve')
            ->where('id', '!=', Auth::id())
            ->get();
        foreach ($approvers as $approver) {
            $approver->notify(new NewRequestNotification($requestModel));
        }

        return redirect()->route('requests.index')->with('success', 'La demande a été créée avec succès.');
    }

    /**
     * Modifier une demande (uniquement si en attente)
     */
    public function update(Request $httpRequest, RequestModel $request)
    {
        Gate::authorize('update', $request);

        $user = Auth::user();
        $validated = $httpRequest->validate([
            'department_id' => 'required|exists:departments,id',
            'product_id' => 'required|exists:products,id',
            'quantity' => 'required|integer|min:1',
            'comments' => 'nullable|string|max:255',
        ]);

        // Responsable du département : ne peut modifier que pour son département
        if ($user->hasRole('Responsable du département') && $user->department_id) {
            if ((int) $validated['department_id'] !== (int) $user->department_id) {
                abort(403, 'Vous ne pouvez modifier que pour votre département.');
            }
        }

        // Mettre à jour la demande
        $request->update([
            'department_id' => $validated['department_id'],
            'comments' => $validated['comments'] ?? null,
        ]);

        // Mettre à jour le produit et la quantité
        $firstDetail = $request->requestDetails->first();

        // Si le produit existe, mettre à jour la quantité
        if ($firstDetail) {
            $firstDetail->update([
                'product_id' => $validated['product_id'],
                'quantity' => $validated['quantity'],
            ]);
        } else {
            // Si le produit n'existe pas, créer un nouveau détail
            $request->requestDetails()->create([
                'product_id' => $validated['product_id'],
                'quantity' => $validated['quantity'],
            ]);
        }

        return redirect()->route('requests.index')->with('success', 'La demande a été modifiée avec succès.');
    }

    /**
     * Approuver une demande
     */
    public function approve(RequestModel $request)
    {
        // Vérifier l'autorisation
        Gate::authorize('approve', $request);

        // Mettre à jour le statut
        $request->update([
            'status' => 'validée',
            'approved_by' => Auth::id(),
            'approved_at' => now(),
        ]);

        // Envoyer une notification + email au responsable (créateur) que la demande est validée
        $responsable = $request->user ?? $request->createdBy;
        if ($responsable) {
            $responsable->notify(new RequestStatusNotification($request, 'validée', Auth::user()));
        }

        // Notifier les Contrôleurs que la demande validée est en attente de sortie du stock
        $controleurs = User::role('Contrôleur')->get();
        foreach ($controleurs as $controleur) {
            $controleur->notify(new ValidatedRequestPendingSortieNotification($request));
        }

        return redirect()->back()->with('success', 'La demande a été approuvée avec succès !');
    }

    /**
     * Rejeter une demande
     */
    public function reject(Request $httpRequest, RequestModel $request)
    {
        // Vérifier l'autorisation
        Gate::authorize('reject', $request);

        // Validation du motif de rejet (obligatoire)
        $httpRequest->validate([
            'rejection_reason' => 'required|string|max:500',
        ]);

        // Mettre à jour le statut
        $request->update([
            'status' => 'rejetée',
            'rejected_by' => Auth::id(),
            'rejected_at' => now(),
            'rejection_reason' => $httpRequest->input('rejection_reason'),
        ]);

        // Envoyer une notification + email au responsable (créateur) que sa demande est rejetée
        $responsable = $request->user ?? $request->createdBy;
        if ($responsable) {
            $responsable->notify(new RequestStatusNotification($request, 'rejetée', Auth::user()));
        }

        return redirect()->back()->with('success', 'La demande a été rejetée.');
    }

    /**
     * Export des demandes (avec filtres appliqués).
     * Responsable : exporte uniquement les demandes de son département.
     */
    public function export(Request $request)
    {
        if (!auth()->user()->hasPermissionTo('requests.view')) {
            abort(403, 'Vous n\'êtes pas autorisé à exporter les demandes.');
        }

        $user = Auth::user();
        $search = $request->get('search');
        $status = $request->get('status');
        $departmentId = $request->get('department_id') ? (int) $request->get('department_id') : null;
        $date = $request->get('date');

        $isResponsable = $user->hasRole('Responsable du département');
        $isMagasinier = $user->hasRole('Magasinier');

        // Responsable : ignore le filtre département, force son département
        if ($isResponsable && $user->department_id) {
            $departmentId = null; // sera géré par userDepartmentId
        }

        $export = new RequestsExport(
            search: $search,
            status: $status,
            departmentId: $departmentId,
            date: $date,
            userDepartmentId: $user->department_id,
            createdBy: $user->id,
            isResponsable: $isResponsable,
            isMagasinier: $isMagasinier
        );

        $filename = 'demandes_' . now()->format('Y-m-d_His') . '.xlsx';

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

    /**
     * Marquer une notification comme lue
     */
    public function markNotificationAsRead($notificationId)
    {
        $notification = Auth::user()->notifications()->findOrFail($notificationId);
        $notification->markAsRead();

        return redirect()->back();
    }

    /**
     * Marquer toutes les notifications comme lues
     */
    public function markAllNotificationsAsRead()
    {
        Auth::user()->unreadNotifications->markAsRead();

        return redirect()->back()->with('success', 'Toutes les notifications ont été marquées comme lues.');
    }
}
