<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use App\Models\ShippingZone;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class ShippingController extends Controller
{
    /**
     * Calcular frete baseado no endereço
     * POST /api/shipping/calculate
     */
    public function calculate(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'city' => 'required|string',
            'district' => 'required|string',
            'zip_code' => 'nullable|string',
            'items' => 'required|array',
            'items.*.product_id' => 'required|integer',
            'items.*.quantity' => 'required|integer|min:1',
            'items.*.weight' => 'nullable|numeric|min:0',
            'total' => 'required|numeric|min:0',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Dados inválidos',
                'errors' => $validator->errors()
            ], 422);
        }

        // Buscar zonas de envio que atendem a cidade
        $zones = ShippingZone::where('active', true)
            ->where(function($query) use ($request) {
                $query->whereJsonContains('cities', $request->city)
                      ->orWhereJsonContains('cities', strtolower($request->city))
                      ->orWhereJsonContains('cities', strtoupper($request->city));
            })
            ->get();

        if ($zones->isEmpty()) {
            // Retornar frete padrão se não encontrar zona
            return response()->json([
                'success' => true,
                'data' => [
                    [
                        'id' => 0,
                        'name' => 'Entrega Padrão',
                        'price' => $request->total >= 2000 ? 0 : 150,
                        'delivery_days' => 3,
                        'description' => 'Entrega em 2-3 dias úteis',
                    ]
                ]
            ]);
        }

        $methods = [];

        foreach ($zones as $zone) {
            // Calcular peso total dos itens
            $totalWeight = 0;
            foreach ($request->items as $item) {
                $weight = $item['weight'] ?? 0.5; // Peso padrão 0.5kg se não informado
                $totalWeight += $weight * $item['quantity'];
            }

            // Calcular preço base
            $price = $zone->base_price;

            // Adicionar custo por peso
            if ($zone->price_per_kg && $totalWeight > 0) {
                $price += $totalWeight * $zone->price_per_kg;
            }

            // Verificar frete grátis
            if ($zone->free_shipping_min && $request->total >= $zone->free_shipping_min) {
                $price = 0;
            }

            $methods[] = [
                'id' => $zone->id,
                'name' => $zone->name,
                'price' => round($price, 2),
                'delivery_days' => $zone->delivery_days,
                'description' => $zone->description,
                'free_shipping' => $price == 0,
            ];
        }

        // Ordenar por preço (menor primeiro)
        usort($methods, function($a, $b) {
            return $a['price'] <=> $b['price'];
        });

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

    /**
     * Listar métodos de envio disponíveis
     * GET /api/shipping/methods
     * GET /api/shipping/methods?city=Maputo  (filtrar por cidade — opcional)
     */
    public function methods(Request $request)
    {
        $query = ShippingZone::where('active', true)->orderBy('base_price');

        // Se uma cidade for fornecida, filtrar por ela; caso contrário devolver todos
        if ($request->filled('city')) {
            $city = $request->city;
            $query->where(function ($q) use ($city) {
                $q->whereJsonContains('cities', $city)
                  ->orWhereJsonContains('cities', strtolower($city))
                  ->orWhereJsonContains('cities', strtoupper($city));
            });
        }

        $zones = $query->get()->map(function ($zone) {
            return [
                'id'           => $zone->id,
                'name'         => $zone->name,
                'description'  => $zone->description ?? '',
                'base_price'   => (float) $zone->base_price,
                'delivery_days'=> (int) $zone->delivery_days,
                'active'       => (bool) $zone->active,
            ];
        });

        // Se não houver nenhuma zona configurada, devolver um método padrão
        if ($zones->isEmpty()) {
            $zones = collect([[
                'id'            => 1,
                'name'          => 'Entrega Padrão',
                'description'   => 'Entrega em 2-3 dias úteis',
                'base_price'    => 150.0,
                'delivery_days' => 3,
                'active'        => true,
            ]]);
        }

        return response()->json([
            'success' => true,
            'data'    => $zones->values(),
        ]);
    }

    /**
     * Buscar endereço por CEP/código postal
     * GET /api/shipping/address/{zipCode}
     */
    public function getAddress($zipCode)
    {
        // Aqui você pode integrar com um serviço de CEP
        // Por enquanto, retornar dados mockados para Moçambique
        
        // Remover caracteres não numéricos
        $zipCode = preg_replace('/[^0-9]/', '', $zipCode);

        // Dados mockados (você pode integrar com API real)
        $addresses = [
            '1100' => [
                'zip_code' => '1100',
                'city' => 'Maputo',
                'district' => 'Sommerschield',
                'state' => 'Maputo',
            ],
            '3100' => [
                'zip_code' => '3100',
                'city' => 'Nampula',
                'district' => 'Centro',
                'state' => 'Nampula',
            ],
        ];

        if (isset($addresses[$zipCode])) {
            return response()->json([
                'success' => true,
                'data' => $addresses[$zipCode]
            ]);
        }

        return response()->json([
            'success' => false,
            'message' => 'CEP não encontrado'
        ], 404);
    }

    /**
     * Listar todas as zonas de envio (Admin)
     * GET /api/shipping/zones
     */
    public function zones()
    {
        $zones = ShippingZone::orderBy('name')->get();

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

    /**
     * Criar nova zona de envio (Admin)
     * POST /api/shipping/zones
     */
    public function createZone(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'cities' => 'required|array',
            'cities.*' => 'string',
            'districts' => 'nullable|array',
            'districts.*' => 'string',
            'base_price' => 'required|numeric|min:0',
            'price_per_kg' => 'nullable|numeric|min:0',
            'free_shipping_min' => 'nullable|numeric|min:0',
            'delivery_days' => 'required|integer|min:1',
            'description' => 'nullable|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Dados inválidos',
                'errors' => $validator->errors()
            ], 422);
        }

        $zone = ShippingZone::create([
            'name' => $request->name,
            'cities' => $request->cities,
            'districts' => $request->districts ?? [],
            'base_price' => $request->base_price,
            'price_per_kg' => $request->price_per_kg,
            'free_shipping_min' => $request->free_shipping_min,
            'delivery_days' => $request->delivery_days,
            'description' => $request->description,
            'active' => true,
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Zona de envio criada com sucesso!',
            'data' => $zone
        ], 201);
    }

    /**
     * Atualizar zona de envio (Admin)
     * PUT /api/shipping/zones/{id}
     */
    public function updateZone(Request $request, $id)
    {
        $zone = ShippingZone::find($id);

        if (!$zone) {
            return response()->json([
                'success' => false,
                'message' => 'Zona de envio não encontrada'
            ], 404);
        }

        $validator = Validator::make($request->all(), [
            'name' => 'sometimes|string|max:255',
            'cities' => 'sometimes|array',
            'cities.*' => 'string',
            'districts' => 'nullable|array',
            'districts.*' => 'string',
            'base_price' => 'sometimes|numeric|min:0',
            'price_per_kg' => 'nullable|numeric|min:0',
            'free_shipping_min' => 'nullable|numeric|min:0',
            'delivery_days' => 'sometimes|integer|min:1',
            'description' => 'nullable|string',
            'active' => 'sometimes|boolean',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Dados inválidos',
                'errors' => $validator->errors()
            ], 422);
        }

        $zone->update($request->only([
            'name', 'cities', 'districts', 'base_price', 'price_per_kg',
            'free_shipping_min', 'delivery_days', 'description', 'active'
        ]));

        return response()->json([
            'success' => true,
            'message' => 'Zona de envio atualizada com sucesso!',
            'data' => $zone
        ]);
    }

    /**
     * Deletar zona de envio (Admin)
     * DELETE /api/shipping/zones/{id}
     */
    public function destroyZone($id)
    {
        $zone = ShippingZone::find($id);

        if (!$zone) {
            return response()->json([
                'success' => false,
                'message' => 'Zona de envio não encontrada'
            ], 404);
        }

        $zone->delete();

        return response()->json([
            'success' => true,
            'message' => 'Zona de envio deletada com sucesso!'
        ]);
    }

    /**
     * Ativar/Desativar zona de envio (Admin)
     * PUT /api/shipping/zones/{id}/toggle
     */
    public function toggleZone($id)
    {
        $zone = ShippingZone::find($id);

        if (!$zone) {
            return response()->json([
                'success' => false,
                'message' => 'Zona de envio não encontrada'
            ], 404);
        }

        $zone->active = !$zone->active;
        $zone->save();

        return response()->json([
            'success' => true,
            'message' => $zone->active ? 'Zona ativada!' : 'Zona desativada!',
            'data' => $zone
        ]);
    }

    /**
     * Obter cidades atendidas
     * GET /api/shipping/cities
     */
    public function cities()
    {
        $zones = ShippingZone::where('active', true)->get();
        
        $cities = [];
        foreach ($zones as $zone) {
            foreach ($zone->cities as $city) {
                if (!in_array($city, $cities)) {
                    $cities[] = $city;
                }
            }
        }

        sort($cities);

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