<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\ShippingFee;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ShippingFeeController extends Controller
{
    // Drapeaux des pays
    private $countryFlags = [
        'RD Congo' => '🇨🇩',
        'Congo-Brazzaville' => '🇨🇬',
        'Gabon' => '🇬🇦',
        'Cameroun' => '🇨🇲',
        'Tchad' => '🇹🇩',
        'Centrafrique' => '🇨🇫',
        'Guinée Équatoriale' => '🇬🇶',
        'Côte d\'Ivoire' => '🇨🇮',
        'Sénégal' => '🇸🇳',
        'Mali' => '🇲🇱',
        'Burkina Faso' => '🇧🇫',
        'Niger' => '🇳🇪',
        'Bénin' => '🇧🇯',
        'Togo' => '🇹🇬',
        'Guinée' => '🇬🇳',
        'Ghana' => '🇬🇭',
        'Nigéria' => '🇳🇬',
        'Rwanda' => '🇷🇼',
        'Burundi' => '🇧🇮',
        'Kenya' => '🇰🇪',
        'Tanzanie' => '🇹🇿',
        'Ouganda' => '🇺🇬',
        'Éthiopie' => '🇪🇹',
        'Maroc' => '🇲🇦',
        'Algérie' => '🇩🇿',
        'Tunisie' => '🇹🇳',
        'Angola' => '🇦🇴',
        'Zambie' => '🇿🇲',
        'Zimbabwe' => '🇿🇼',
        'Mozambique' => '🇲🇿',
        'Afrique du Sud' => '🇿🇦',
        'Madagascar' => '🇲🇬',
        'France' => '🇫🇷',
        'Belgique' => '🇧🇪',
        'Suisse' => '🇨🇭',
        'Canada' => '🇨🇦',
        'États-Unis' => '🇺🇸',
        'Haïti' => '🇭🇹',
    ];

    /**
     * Invalider le cache des shipping fees
     */
    private function clearShippingCache($country = null)
    {
        cache()->forget('shipping_fees_index_data');
        if ($country) {
            cache()->forget('shipping_zones_' . md5($country));
        }
    }

    public function index(Request $request)
    {
        try {
            // Cache unique pour toutes les données (évite plusieurs requêtes)
            $cacheKey = 'shipping_fees_index_data';
            $data = cache()->remember($cacheKey, 300, function() {
                // Une seule requête pour les stats globales
                $globalStats = DB::table('shipping_fees')
                    ->selectRaw('COUNT(*) as total_zones')
                    ->selectRaw('COUNT(DISTINCT country) as countries')
                    ->selectRaw('AVG(fee) as avg_fee')
                    ->selectRaw('MIN(fee) as min_fee')
                    ->selectRaw('MAX(fee) as max_fee')
                    ->selectRaw('SUM(CASE WHEN is_active = 1 THEN 1 ELSE 0 END) as active')
                    ->selectRaw('SUM(CASE WHEN is_active = 0 THEN 1 ELSE 0 END) as inactive')
                    ->first();
                
                // Une seule requête pour les pays avec leurs stats
                $countriesWithCount = DB::table('shipping_fees')
                    ->select('country')
                    ->selectRaw('COUNT(*) as zones_count')
                    ->selectRaw('SUM(CASE WHEN is_active = 1 THEN 1 ELSE 0 END) as active_count')
                    ->selectRaw('ROUND(AVG(fee), 0) as avg_fee')
                    ->groupBy('country')
                    ->orderBy('country')
                    ->get()
                    ->keyBy('country');
                
                return [
                    'stats' => [
                        'countries' => $globalStats->countries ?? 0,
                        'cities' => $globalStats->total_zones ?? 0,
                        'total_zones' => $globalStats->total_zones ?? 0,
                        'avg_fee' => round($globalStats->avg_fee ?? 0),
                        'min_fee' => $globalStats->min_fee ?? 0,
                        'max_fee' => $globalStats->max_fee ?? 0,
                        'active' => $globalStats->active ?? 0,
                        'inactive' => $globalStats->inactive ?? 0,
                    ],
                    'countriesWithCount' => $countriesWithCount,
                ];
            });
            
            return view('admin.shipping-fees.index', [
                'countries' => $data['countriesWithCount']->keys(),
                'countriesWithCount' => $data['countriesWithCount'],
                'stats' => $data['stats'],
                'countryFlags' => $this->countryFlags,
            ]);
            
        } catch (\Exception $e) {
            Log::error('Erreur ShippingFee index: ' . $e->getMessage());
            return redirect()->back()->with('error', 'Erreur lors du chargement des frais de livraison.');
        }
    }

    /**
     * Charger les zones d'un pays via AJAX (avec cache)
     */
    public function getCountryZones(Request $request, $country)
    {
        try {
            // Utiliser Eloquent pour avoir les modèles complets (nécessaire pour route())
            $fees = ShippingFee::where('country', $country)
                ->select(['id', 'country', 'city', 'district', 'fee', 'free_shipping_minimum', 'estimated_days', 'is_active'])
                ->orderBy('city')
                ->orderBy('district')
                ->get();
            
            // Grouper par ville
            $citiesGrouped = $fees->groupBy('city');
            
            $html = view('admin.shipping-fees.partials.country-zones', [
                'country' => $country,
                'fees' => $fees,
                'citiesGrouped' => $citiesGrouped,
                'countryFlags' => $this->countryFlags,
            ])->render();
            
            return response()->json([
                'success' => true,
                'html' => $html,
                'count' => $fees->count(),
                'cities_count' => $citiesGrouped->count(),
            ]);
            
        } catch (\Exception $e) {
            Log::error('Erreur getCountryZones: ' . $e->getMessage());
            return response()->json(['success' => false, 'message' => 'Erreur de chargement'], 500);
        }
    }

    public function create()
    {
        try {
            $countries = config('countries', []);
            return view('admin.shipping-fees.create', compact('countries'));
            
        } catch (\Exception $e) {
            Log::error('Erreur ShippingFee create: ' . $e->getMessage());
            return redirect()->route('admin.shipping-fees.index')
                ->with('error', 'Erreur lors du chargement du formulaire.');
        }
    }

    public function store(Request $request)
    {
        DB::beginTransaction();
        
        try {
            $validated = $request->validate([
                'country' => 'required|string|max:255',
                'city' => 'nullable|string|max:255',
                'district' => 'nullable|string|max:255',
                'fee' => 'required|numeric|min:0',
                'free_shipping_minimum' => 'nullable|numeric|min:0',
                'estimated_days' => 'nullable|integer|min:1|max:30',
                'is_active' => 'boolean'
            ]);

            // Vérifier si la combinaison exacte existe déjà
            $city = !empty($validated['city']) ? $validated['city'] : null;
            $district = !empty($validated['district']) ? $validated['district'] : null;
            
            $existingFee = ShippingFee::where('country', $validated['country'])
                ->where(function($query) use ($city) {
                    if ($city) {
                        $query->where('city', $city);
                    } else {
                        $query->whereNull('city');
                    }
                })
                ->where(function($query) use ($district) {
                    if ($district) {
                        $query->where('district', $district);
                    } else {
                        $query->whereNull('district');
                    }
                })
                ->first();

            if ($existingFee) {
                return back()->with('error', 'Des frais de livraison existent déjà pour cette zone exacte (pays/ville/quartier).');
            }

            // Validation logique : Si quartier spécifié, ville doit l'être aussi
            if ($district && !$city) {
                return back()->with('error', 'Vous devez spécifier une ville si vous spécifiez un quartier.')->withInput();
            }

            $validated['is_active'] = $request->boolean('is_active', true);
            $validated['city'] = $city;
            $validated['district'] = $district;

            ShippingFee::create($validated);
            
            // Invalider le cache
            $this->clearShippingCache($validated['country']);
            
            DB::commit();

            $zone = $district ? "{$city} - {$district}" : ($city ? $city : $validated['country']);
            return redirect()->route('admin.shipping-fees.index')
                ->with('success', "Frais de livraison ajoutés pour {$zone} avec succès.");

        } catch (\Illuminate\Validation\ValidationException $e) {
            DB::rollBack();
            return back()->withErrors($e->errors())->withInput();
            
        } catch (\Exception $e) {
            DB::rollBack();
            \Illuminate\Support\Facades\Log::error('Erreur ShippingFee store: ' . $e->getMessage());
            return back()->with('error', 'Erreur lors de l\'ajout des frais de livraison.')->withInput();
        }
    }

    public function edit(ShippingFee $shippingFee)
    {
        try {
            $countries = config('countries', []);
            return view('admin.shipping-fees.edit', compact('shippingFee', 'countries'));
            
        } catch (\Exception $e) {
            Log::error('Erreur ShippingFee edit: ' . $e->getMessage());
            return redirect()->route('admin.shipping-fees.index')
                ->with('error', 'Erreur lors du chargement du formulaire.');
        }
    }

    public function update(Request $request, ShippingFee $shippingFee)
    {
        DB::beginTransaction();
        
        try {
            $validated = $request->validate([
                'country' => 'required|string|max:255',
                'city' => 'nullable|string|max:255',
                'district' => 'nullable|string|max:255',
                'fee' => 'required|numeric|min:0',
                'free_shipping_minimum' => 'nullable|numeric|min:0',
                'estimated_days' => 'nullable|integer|min:1|max:30',
                'is_active' => 'boolean'
            ]);

            // Vérifier les doublons (exclure l'enregistrement actuel)
            $existingFee = ShippingFee::where('country', $validated['country'])
                ->where('city', $validated['city'] ?? null)
                ->where('district', $validated['district'] ?? null)
                ->where('id', '!=', $shippingFee->id)
                ->first();

            if ($existingFee) {
                return back()->with('error', 'Des frais de livraison existent déjà pour cette zone.');
            }

            $validated['is_active'] = $request->boolean('is_active');
            $validated['city'] = !empty($validated['city']) ? $validated['city'] : null;
            $validated['district'] = !empty($validated['district']) ? $validated['district'] : null;

            $shippingFee->update($validated);
            
            // Invalider le cache
            $this->clearShippingCache($validated['country']);
            
            DB::commit();

            return redirect()->route('admin.shipping-fees.index')
                ->with('success', 'Frais de livraison modifiés avec succès.');

        } catch (\Illuminate\Validation\ValidationException $e) {
            DB::rollBack();
            return back()->withErrors($e->errors())->withInput();
            
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Erreur ShippingFee update: ' . $e->getMessage());
            return back()->with('error', 'Erreur lors de la modification des frais de livraison.')->withInput();
        }
    }

    public function destroy(Request $request, ShippingFee $shippingFee)
    {
        DB::beginTransaction();
        
        try {
            $country = $shippingFee->country;
            $shippingFee->delete();
            
            // Invalider le cache
            $this->clearShippingCache($country);
            
            DB::commit();

            // Si c'est une requête AJAX, retourner JSON
            if ($request->ajax() || $request->wantsJson()) {
                return response()->json([
                    'success' => true,
                    'message' => 'Frais de livraison supprimés avec succès.'
                ]);
            }

            return redirect()->route('admin.shipping-fees.index')
                ->with('success', 'Frais de livraison supprimés avec succès.');

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Erreur ShippingFee destroy: ' . $e->getMessage());
            
            // Si c'est une requête AJAX, retourner JSON
            if ($request->ajax() || $request->wantsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Erreur lors de la suppression des frais de livraison.'
                ], 500);
            }

            return redirect()->route('admin.shipping-fees.index')
                ->with('error', 'Erreur lors de la suppression des frais de livraison.');
        }
    }

    public function calculate(Request $request)
    {
        try {
            $validated = $request->validate([
                'country' => 'required|string',
                'city' => 'nullable|string',
                'district' => 'nullable|string',
                'subtotal' => 'nullable|numeric|min:0'
            ]);

            $country = $validated['country'];
            $city = $validated['city'] ?? null;
            $district = $validated['district'] ?? null;
            $subtotal = $validated['subtotal'] ?? 0;

            $query = ShippingFee::where('is_active', true)
                ->where('country', $country);

            // Recherche spécifique par district
            if ($district && $city) {
                $shippingFee = (clone $query)
                    ->where('city', $city)
                    ->where('district', $district)
                    ->first();
                    
                if ($shippingFee) {
                    return $this->formatShippingResponse($shippingFee, $subtotal);
                }
            }

            // Recherche par ville
            if ($city) {
                $shippingFee = (clone $query)
                    ->where('city', $city)
                    ->whereNull('district')
                    ->first();
                    
                if ($shippingFee) {
                    return $this->formatShippingResponse($shippingFee, $subtotal);
                }
            }

            // Recherche par pays (par défaut)
            $shippingFee = $query
                ->whereNull('city')
                ->whereNull('district')
                ->first();

            if ($shippingFee) {
                return $this->formatShippingResponse($shippingFee, $subtotal);
            }

            return response()->json([
                'success' => false,
                'message' => 'Aucun frais de livraison trouvé pour cette zone'
            ], 404);

        } catch (\Exception $e) {
            Log::error('Erreur ShippingFee calculate: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Erreur lors du calcul des frais de livraison'
            ], 500);
        }
    }

    private function formatShippingResponse($shippingFee, $subtotal)
    {
        $fee = $this->applyFreeShipping($shippingFee, $subtotal);
        
        return response()->json([
            'success' => true,
            'fee' => $fee,
            'estimated_days' => $shippingFee->estimated_days,
            'is_free' => $fee == 0 && $shippingFee->fee > 0,
            'shipping_fee' => $shippingFee
        ]);
    }

    private function applyFreeShipping($shippingFee, $subtotal)
    {
        if ($shippingFee->free_shipping_minimum && $subtotal >= $shippingFee->free_shipping_minimum) {
            return 0;
        }
        return $shippingFee->fee;
    }

    public function getCities(Request $request)
    {
        try {
            $validated = $request->validate([
                'country' => 'required|string'
            ]);

            $country = $validated['country'];
            $countries = config('countries', []);
            
            $cities = $countries[$country] ?? [];
            
            return response()->json($cities);

        } catch (\Exception $e) {
            Log::error('Erreur ShippingFee getCities: ' . $e->getMessage());
            return response()->json([], 500);
        }
    }

    public function getDistricts(Request $request)
    {
        try {
            $validated = $request->validate([
                'country' => 'required|string',
                'city' => 'required|string'
            ]);

            $country = $validated['country'];
            $city = $validated['city'];
            
            $districts = ShippingFee::where('country', $country)
                ->where('city', $city)
                ->whereNotNull('district')
                ->where('is_active', true)
                ->pluck('district')
                ->unique()
                ->values();
            
            return response()->json($districts);

        } catch (\Exception $e) {
            Log::error('Erreur ShippingFee getDistricts: ' . $e->getMessage());
            return response()->json([], 500);
        }
    }

    /**
     * Mise à jour du tarif en ligne (AJAX)
     */
    public function updateFee(Request $request, $id)
    {
        try {
            $validated = $request->validate([
                'fee' => 'required|numeric|min:0'
            ]);

            $shippingFee = ShippingFee::findOrFail($id);
            $shippingFee->update(['fee' => $validated['fee']]);
            
            // Invalider le cache
            $this->clearShippingCache($shippingFee->country);

            return response()->json([
                'success' => true,
                'message' => 'Tarif mis à jour'
            ]);

        } catch (\Exception $e) {
            Log::error('Erreur updateFee: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Erreur lors de la mise à jour'
            ], 500);
        }
    }

    /**
     * Toggle statut actif/inactif (AJAX)
     */
    public function toggleStatus(Request $request, $id)
    {
        try {
            $shippingFee = ShippingFee::findOrFail($id);
            $shippingFee->update(['is_active' => $request->boolean('is_active')]);
            
            // Invalider le cache
            $this->clearShippingCache($shippingFee->country);

            return response()->json([
                'success' => true,
                'message' => $request->boolean('is_active') ? 'Zone activée' : 'Zone désactivée'
            ]);

        } catch (\Exception $e) {
            Log::error('Erreur toggleStatus: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Erreur lors de la mise à jour'
            ], 500);
        }
    }

    /**
     * Suppression AJAX
     */
    public function destroyAjax($id)
    {
        try {
            $shippingFee = ShippingFee::findOrFail($id);
            $country = $shippingFee->country;
            $shippingFee->delete();
            
            // Invalider le cache
            $this->clearShippingCache($country);;

            return response()->json([
                'success' => true,
                'message' => 'Zone supprimée'
            ]);

        } catch (\Exception $e) {
            Log::error('Erreur destroyAjax: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Erreur lors de la suppression'
            ], 500);
        }
    }

    /**
     * Actions en masse (activer, désactiver, supprimer)
     */
    public function massAction(Request $request)
    {
        try {
            $validated = $request->validate([
                'ids' => 'required|array',
                'ids.*' => 'integer',
                'action' => 'required|in:activate,deactivate,delete'
            ]);

            $ids = $validated['ids'];
            $action = $validated['action'];
            $count = count($ids);

            switch ($action) {
                case 'activate':
                    ShippingFee::whereIn('id', $ids)->update(['is_active' => true]);
                    $message = "{$count} zones activées";
                    break;
                    
                case 'deactivate':
                    ShippingFee::whereIn('id', $ids)->update(['is_active' => false]);
                    $message = "{$count} zones désactivées";
                    break;
                    
                case 'delete':
                    ShippingFee::whereIn('id', $ids)->delete();
                    $message = "{$count} zones supprimées";
                    break;
            }
            
            // Invalider tout le cache (actions en masse peuvent toucher plusieurs pays)
            $this->clearShippingCache();

            return response()->json([
                'success' => true,
                'message' => $message
            ]);

        } catch (\Exception $e) {
            Log::error('Erreur massAction: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Erreur lors de l\'action en masse'
            ], 500);
        }
    }

    /**
     * Mise à jour en masse des tarifs
     */
    public function massUpdate(Request $request)
    {
        try {
            $validated = $request->validate([
                'ids' => 'required|array',
                'ids.*' => 'integer',
                'type' => 'required|in:fixed,percentage_increase,percentage_decrease,add,subtract',
                'value' => 'required|numeric|min:0'
            ]);

            $ids = $validated['ids'];
            $type = $validated['type'];
            $value = $validated['value'];
            $updated = 0;

            $fees = ShippingFee::whereIn('id', $ids)->get();

            foreach ($fees as $fee) {
                $newFee = $fee->fee;
                
                switch ($type) {
                    case 'fixed':
                        $newFee = $value;
                        break;
                    case 'percentage_increase':
                        $newFee = $fee->fee * (1 + $value / 100);
                        break;
                    case 'percentage_decrease':
                        $newFee = $fee->fee * (1 - $value / 100);
                        break;
                    case 'add':
                        $newFee = $fee->fee + $value;
                        break;
                    case 'subtract':
                        $newFee = max(0, $fee->fee - $value);
                        break;
                }
                
                $fee->update(['fee' => round($newFee, 2)]);
                $updated++;
            }
            
            // Invalider tout le cache
            $this->clearShippingCache();

            return response()->json([
                'success' => true,
                'updated' => $updated,
                'message' => "{$updated} zones mises à jour"
            ]);

        } catch (\Exception $e) {
            Log::error('Erreur massUpdate: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Erreur lors de la mise à jour en masse'
            ], 500);
        }
    }

    /**
     * Synchroniser avec cities.php
     */
    public function sync()
    {
        try {
            $cities = config('cities', []);
            
            if (empty($cities)) {
                return response()->json([
                    'success' => false,
                    'message' => 'Le fichier cities.php est vide'
                ], 400);
            }

            $defaultFee = 1500;
            $defaultDistrict = 'Centre-ville';
            $added = 0;

            foreach ($cities as $country => $citiesList) {
                foreach ($citiesList as $city) {
                    $exists = ShippingFee::where('country', $country)
                        ->where('city', $city)
                        ->exists();
                    
                    if (!$exists) {
                        ShippingFee::create([
                            'country' => $country,
                            'city' => $city,
                            'district' => $defaultDistrict,
                            'fee' => $defaultFee,
                            'is_active' => true,
                        ]);
                        $added++;
                    }
                }
            }
            
            // Invalider tout le cache
            $this->clearShippingCache();

            return response()->json([
                'success' => true,
                'added' => $added,
                'message' => "{$added} nouvelles zones ajoutées"
            ]);

        } catch (\Exception $e) {
            Log::error('Erreur sync: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Erreur lors de la synchronisation'
            ], 500);
        }
    }
}