<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\PromotionalCampaign;
use App\Models\ProductSheet;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Carbon\Carbon;

class PromotionalCampaignController extends Controller
{
    /**
     * Lista todas as campanhas do usuário
     */
    public function index(Request $request): JsonResponse
    {
        $userId = $request->user()->id;
        
        $query = PromotionalCampaign::ofUser($userId)
            ->withCount('products');
        
        // Filtro por status
        if ($request->has('status')) {
            switch ($request->status) {
                case 'active':
                    $query->active()->current();
                    break;
                case 'scheduled':
                    $query->active()->upcoming();
                    break;
                case 'ended':
                    $query->where('end_date', '<', Carbon::now());
                    break;
                case 'inactive':
                    $query->where('is_active', false);
                    break;
            }
        }
        
        $campaigns = $query->orderBy('start_date', 'desc')->get()->map(function ($campaign) {
            return array_merge($campaign->toArray(), [
                'status' => $campaign->status,
                'days_remaining' => $campaign->days_remaining,
                'is_currently_active' => $campaign->isCurrentlyActive(),
            ]);
        });
        
        return response()->json($campaigns);
    }

    /**
     * Cria uma nova campanha
     */
    public function store(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'code' => 'nullable|string|max:50',
            'description' => 'nullable|string',
            'discount_type' => 'required|in:percentage,fixed,price_override',
            'discount_value' => 'required|numeric|min:0',
            'start_date' => 'required|date',
            'end_date' => 'required|date|after_or_equal:start_date',
            'start_time' => 'nullable|date_format:H:i',
            'end_time' => 'nullable|date_format:H:i',
            'is_active' => 'boolean',
            'apply_to_all_products' => 'boolean',
            'min_price' => 'nullable|numeric|min:0',
            'show_original_price' => 'boolean',
            'show_discount_badge' => 'boolean',
            'badge_text' => 'nullable|string|max:50',
            'badge_color' => 'nullable|string|max:20',
            'priority' => 'integer|min:0',
            'product_ids' => 'nullable|array',
            'product_ids.*' => 'exists:product_sheets,id',
            'preset' => 'nullable|string', // Para usar presets
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $userId = $request->user()->id;
        $data = $validator->validated();
        
        // Aplicar preset se fornecido
        if (!empty($data['preset']) && isset(PromotionalCampaign::PRESETS[$data['preset']])) {
            $preset = PromotionalCampaign::PRESETS[$data['preset']];
            $data = array_merge($preset, $data);
        }
        
        unset($data['product_ids'], $data['preset']);
        $data['user_id'] = $userId;

        DB::beginTransaction();
        
        try {
            $campaign = PromotionalCampaign::create($data);
            
            // Adicionar produtos se fornecidos
            if ($request->has('product_ids') && is_array($request->product_ids)) {
                foreach ($request->product_ids as $productId) {
                    $product = ProductSheet::ofUser($userId)->find($productId);
                    if ($product) {
                        $promoPrice = $campaign->calculatePromotionalPrice($product);
                        $campaign->products()->attach($productId, [
                            'promotional_price' => $promoPrice,
                        ]);
                    }
                }
            }
            
            // Se apply_to_all_products, adicionar todos
            if ($campaign->apply_to_all_products) {
                $campaign->applyToAllProducts();
            }
            
            DB::commit();
            
            $campaign->load('products');
            
            return response()->json(array_merge($campaign->toArray(), [
                'status' => $campaign->status,
                'products_count' => $campaign->products->count(),
            ]), 201);
            
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['message' => 'Erro ao criar campanha: ' . $e->getMessage()], 500);
        }
    }

    /**
     * Exibe uma campanha específica
     */
    public function show(Request $request, $id): JsonResponse
    {
        $campaign = PromotionalCampaign::ofUser($request->user()->id)
            ->with(['products' => function ($query) {
                $query->select('product_sheets.*')
                      ->withPivot(['discount_type', 'discount_value', 'promotional_price', 'promo_margin', 'promo_margin_percent', 'is_profitable']);
            }])
            ->findOrFail($id);
        
        // Adicionar informações de cada produto COM RENTABILIDADE
        $totalProfit = 0;
        $unprofitableCount = 0;
        
        $productsWithInfo = $campaign->products->map(function ($product) use ($campaign, &$totalProfit, &$unprofitableCount) {
            $originalPrice = (float) ($product->final_price ?? $product->sale_price);
            $promoPrice = (float) $product->pivot->promotional_price;
            $cmv = (float) ($product->cmv_total ?? 0);
            
            // Calcular rentabilidade
            $marginInfo = $campaign->getPromotionalMargin($product);
            
            if (!$marginInfo['is_profitable']) {
                $unprofitableCount++;
            }
            $totalProfit += $marginInfo['promo_margin'];
            
            return array_merge($product->toArray(), [
                'original_price' => $originalPrice,
                'promotional_price' => $promoPrice,
                'cmv' => $cmv,
                'discount_percent' => $campaign->getDiscountPercentage($originalPrice, $promoPrice),
                'savings' => round($originalPrice - $promoPrice, 2),
                'badge' => $campaign->getBadgeInfo($originalPrice, $promoPrice),
                // Dados de rentabilidade
                'promo_margin' => $marginInfo['promo_margin'],
                'promo_margin_percent' => $marginInfo['promo_margin_percent'],
                'original_margin' => $marginInfo['original_margin'],
                'original_margin_percent' => $marginInfo['original_margin_percent'],
                'margin_reduction' => $marginInfo['margin_reduction'],
                'is_profitable' => $marginInfo['is_profitable'],
                'is_protected' => $marginInfo['is_protected'],
            ]);
        });
        
        return response()->json(array_merge($campaign->toArray(), [
            'status' => $campaign->status,
            'days_remaining' => $campaign->days_remaining,
            'is_currently_active' => $campaign->isCurrentlyActive(),
            'products' => $productsWithInfo,
            // Resumo de rentabilidade
            'profitability_summary' => [
                'total_profit' => round($totalProfit, 2),
                'unprofitable_count' => $unprofitableCount,
                'all_profitable' => $unprofitableCount === 0,
            ],
        ]));
    }

    /**
     * Atualiza uma campanha
     */
    public function update(Request $request, $id): JsonResponse
    {
        $campaign = PromotionalCampaign::ofUser($request->user()->id)->findOrFail($id);

        $validator = Validator::make($request->all(), [
            'name' => 'sometimes|string|max:255',
            'code' => 'nullable|string|max:50',
            'description' => 'nullable|string',
            'discount_type' => 'sometimes|in:percentage,fixed,price_override',
            'discount_value' => 'sometimes|numeric|min:0',
            'start_date' => 'sometimes|date',
            'end_date' => 'sometimes|date|after_or_equal:start_date',
            'start_time' => 'nullable|date_format:H:i',
            'end_time' => 'nullable|date_format:H:i',
            'is_active' => 'boolean',
            'apply_to_all_products' => 'boolean',
            'min_price' => 'nullable|numeric|min:0',
            'show_original_price' => 'boolean',
            'show_discount_badge' => 'boolean',
            'badge_text' => 'nullable|string|max:50',
            'badge_color' => 'nullable|string|max:20',
            'priority' => 'integer|min:0',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $campaign->update($validator->validated());
        
        // Recalcular preços se desconto mudou
        if ($request->hasAny(['discount_type', 'discount_value', 'min_price'])) {
            $campaign->recalculateAllPrices();
        }
        
        // Se mudou para apply_to_all_products
        if ($request->has('apply_to_all_products') && $campaign->apply_to_all_products) {
            $campaign->applyToAllProducts();
        }
        
        $campaign->load('products');

        return response()->json(array_merge($campaign->toArray(), [
            'status' => $campaign->status,
            'products_count' => $campaign->products->count(),
        ]));
    }

    /**
     * Remove uma campanha
     */
    public function destroy(Request $request, $id): JsonResponse
    {
        $campaign = PromotionalCampaign::ofUser($request->user()->id)->findOrFail($id);
        $campaign->delete();

        return response()->json(['message' => 'Campanha excluída com sucesso']);
    }

    /**
     * Adiciona produtos à campanha
     */
    public function addProducts(Request $request, $id): JsonResponse
    {
        $campaign = PromotionalCampaign::ofUser($request->user()->id)->findOrFail($id);
        
        $validator = Validator::make($request->all(), [
            'product_ids' => 'required|array',
            'product_ids.*' => 'exists:product_sheets,id',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $userId = $request->user()->id;
        $added = 0;
        
        foreach ($request->product_ids as $productId) {
            $product = ProductSheet::ofUser($userId)->find($productId);
            if ($product && !$campaign->products->contains($productId)) {
                $promoPrice = $campaign->calculatePromotionalPrice($product);
                $campaign->products()->attach($productId, [
                    'promotional_price' => $promoPrice,
                ]);
                $added++;
            }
        }

        return response()->json([
            'message' => "{$added} produto(s) adicionado(s) à campanha",
            'products_count' => $campaign->products()->count(),
        ]);
    }

    /**
     * Remove produtos da campanha
     */
    public function removeProducts(Request $request, $id): JsonResponse
    {
        $campaign = PromotionalCampaign::ofUser($request->user()->id)->findOrFail($id);
        
        $validator = Validator::make($request->all(), [
            'product_ids' => 'required|array',
            'product_ids.*' => 'exists:product_sheets,id',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $campaign->products()->detach($request->product_ids);

        return response()->json([
            'message' => 'Produto(s) removido(s) da campanha',
            'products_count' => $campaign->products()->count(),
        ]);
    }

    /**
     * Atualiza desconto específico de um produto na campanha
     */
    public function updateProductDiscount(Request $request, $campaignId, $productId): JsonResponse
    {
        $campaign = PromotionalCampaign::ofUser($request->user()->id)->findOrFail($campaignId);
        
        $validator = Validator::make($request->all(), [
            'discount_type' => 'nullable|in:percentage,fixed,price_override',
            'discount_value' => 'nullable|numeric|min:0',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $product = $campaign->products()->where('product_sheet_id', $productId)->first();
        
        if (!$product) {
            return response()->json(['message' => 'Produto não encontrado na campanha'], 404);
        }

        $override = null;
        if ($request->discount_type) {
            $override = [
                'discount_type' => $request->discount_type,
                'discount_value' => $request->discount_value,
            ];
        }

        $promoPrice = $campaign->calculatePromotionalPrice($product, $override);
        
        $campaign->products()->updateExistingPivot($productId, [
            'discount_type' => $request->discount_type,
            'discount_value' => $request->discount_value,
            'promotional_price' => $promoPrice,
        ]);

        return response()->json([
            'promotional_price' => $promoPrice,
            'message' => 'Desconto atualizado',
        ]);
    }

    /**
     * Retorna presets disponíveis
     */
    public function presets(): JsonResponse
    {
        return response()->json(PromotionalCampaign::getPresets());
    }

    /**
     * Duplica uma campanha
     */
    public function duplicate(Request $request, $id): JsonResponse
    {
        $campaign = PromotionalCampaign::ofUser($request->user()->id)
            ->with('products')
            ->findOrFail($id);
        
        DB::beginTransaction();
        
        try {
            $newCampaign = $campaign->replicate();
            $newCampaign->name = $campaign->name . ' (Cópia)';
            $newCampaign->is_active = false;
            $newCampaign->start_date = Carbon::now();
            $newCampaign->end_date = Carbon::now()->addDays(7);
            $newCampaign->save();
            
            // Copiar produtos
            foreach ($campaign->products as $product) {
                $newCampaign->products()->attach($product->id, [
                    'discount_type' => $product->pivot->discount_type,
                    'discount_value' => $product->pivot->discount_value,
                    'promotional_price' => $product->pivot->promotional_price,
                ]);
            }
            
            DB::commit();
            
            return response()->json(array_merge($newCampaign->toArray(), [
                'status' => $newCampaign->status,
                'products_count' => $newCampaign->products()->count(),
            ]), 201);
            
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['message' => 'Erro ao duplicar: ' . $e->getMessage()], 500);
        }
    }

    /**
     * Preview de preços para uma campanha COM ANÁLISE DE RENTABILIDADE
     */
    public function preview(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'discount_type' => 'required|in:percentage,fixed,price_override',
            'discount_value' => 'required|numeric|min:0',
            'min_price' => 'nullable|numeric|min:0',
            'min_margin_percent' => 'nullable|numeric|min:0',
            'protect_against_loss' => 'nullable|boolean',
            'product_ids' => 'required|array|min:1',
            'product_ids.*' => 'exists:product_sheets,id',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        $userId = $request->user()->id;
        $products = ProductSheet::ofUser($userId)
            ->whereIn('id', $request->product_ids)
            ->get();

        $protectAgainstLoss = $request->protect_against_loss !== false; // default true
        $minMarginPercent = $request->min_margin_percent;

        $unprofitableCount = 0;
        $protectedCount = 0;

        $preview = $products->map(function ($product) use ($request, $protectAgainstLoss, $minMarginPercent, &$unprofitableCount, &$protectedCount) {
            $originalPrice = (float) ($product->final_price ?? $product->sale_price);
            $cmv = (float) ($product->cmv_total ?? 0);
            $promoPrice = $originalPrice;

            // Calcular desconto
            switch ($request->discount_type) {
                case 'percentage':
                    $promoPrice = $originalPrice * (1 - ($request->discount_value / 100));
                    break;
                case 'fixed':
                    $promoPrice = $originalPrice - $request->discount_value;
                    break;
                case 'price_override':
                    $promoPrice = $request->discount_value;
                    break;
            }

            $wasProtected = false;
            $protectionReason = null;

            // Aplicar preço mínimo da campanha
            if ($request->min_price && $promoPrice < $request->min_price) {
                $promoPrice = $request->min_price;
                $wasProtected = true;
                $protectionReason = 'campaign_min_price';
            }

            // Aplicar preço mínimo do produto
            if ($product->min_price && $promoPrice < (float) $product->min_price) {
                $promoPrice = (float) $product->min_price;
                $wasProtected = true;
                $protectionReason = 'product_min_price';
            }

            // Proteção contra prejuízo (nunca vender abaixo do CMV)
            if ($protectAgainstLoss && $cmv > 0 && $promoPrice < $cmv) {
                $promoPrice = $cmv;
                $wasProtected = true;
                $protectionReason = 'cmv_protection';
                $protectedCount++;
            }

            // Margem mínima obrigatória
            if ($minMarginPercent && $cmv > 0) {
                $minPriceWithMargin = $cmv * (1 + ($minMarginPercent / 100));
                if ($promoPrice < $minPriceWithMargin) {
                    $promoPrice = $minPriceWithMargin;
                    $wasProtected = true;
                    $protectionReason = 'min_margin';
                }
            }

            $promoPrice = max(0, round($promoPrice, 2));
            
            // Calcular margens
            $discountPercent = $originalPrice > 0 
                ? round((($originalPrice - $promoPrice) / $originalPrice) * 100, 1)
                : 0;
            
            $promoMargin = $promoPrice - $cmv;
            $promoMarginPercent = $promoPrice > 0 ? round(($promoMargin / $promoPrice) * 100, 1) : 0;
            $originalMargin = $originalPrice - $cmv;
            $originalMarginPercent = $originalPrice > 0 ? round(($originalMargin / $originalPrice) * 100, 1) : 0;
            
            $isProfitable = $promoMargin > 0;
            if (!$isProfitable) {
                $unprofitableCount++;
            }

            return [
                'id' => $product->id,
                'name' => $product->name,
                'sku' => $product->sku,
                'cmv' => $cmv,
                'original_price' => $originalPrice,
                'promotional_price' => $promoPrice,
                'discount_percent' => $discountPercent,
                'savings' => round($originalPrice - $promoPrice, 2),
                // Rentabilidade
                'promo_margin' => round($promoMargin, 2),
                'promo_margin_percent' => $promoMarginPercent,
                'original_margin' => round($originalMargin, 2),
                'original_margin_percent' => $originalMarginPercent,
                'margin_reduction' => round($originalMarginPercent - $promoMarginPercent, 1),
                'is_profitable' => $isProfitable,
                // Proteção
                'was_protected' => $wasProtected,
                'protection_reason' => $protectionReason,
            ];
        });

        $totals = [
            'products_count' => $preview->count(),
            'total_original' => round($preview->sum('original_price'), 2),
            'total_promotional' => round($preview->sum('promotional_price'), 2),
            'total_savings' => round($preview->sum('savings'), 2),
            'avg_discount' => round($preview->avg('discount_percent'), 1),
            // Rentabilidade
            'total_cmv' => round($preview->sum('cmv'), 2),
            'total_promo_margin' => round($preview->sum('promo_margin'), 2),
            'avg_promo_margin_percent' => round($preview->avg('promo_margin_percent'), 1),
            'avg_original_margin_percent' => round($preview->avg('original_margin_percent'), 1),
            // Alertas
            'unprofitable_count' => $unprofitableCount,
            'protected_count' => $protectedCount,
            'all_profitable' => $unprofitableCount === 0,
        ];

        return response()->json([
            'products' => $preview,
            'totals' => $totals,
        ]);
    }
}
