<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Carbon\Carbon;

class PromotionalCampaign extends Model
{
    use HasFactory;

    protected $fillable = [
        'user_id',
        'name',
        'code',
        'description',
        'discount_type',
        'discount_value',
        'start_date',
        'end_date',
        'start_time',
        'end_time',
        'is_active',
        'apply_to_all_products',
        'min_price',
        'min_margin_percent',
        'protect_against_loss',
        'margin_warning_threshold',
        'show_original_price',
        'show_discount_badge',
        'badge_text',
        'badge_color',
        'priority',
    ];

    protected $casts = [
        'start_date' => 'date',
        'end_date' => 'date',
        'is_active' => 'boolean',
        'apply_to_all_products' => 'boolean',
        'protect_against_loss' => 'boolean',
        'show_original_price' => 'boolean',
        'show_discount_badge' => 'boolean',
        'discount_value' => 'decimal:2',
        'min_price' => 'decimal:2',
        'min_margin_percent' => 'decimal:2',
        'margin_warning_threshold' => 'decimal:2',
        'priority' => 'integer',
    ];

    // Tipos de desconto
    const TYPE_PERCENTAGE = 'percentage';
    const TYPE_FIXED = 'fixed';
    const TYPE_PRICE_OVERRIDE = 'price_override';

    // Presets de campanhas
    const PRESETS = [
        'black_friday' => [
            'name' => 'Black Friday',
            'discount_type' => 'percentage',
            'discount_value' => 30,
            'badge_text' => 'BLACK FRIDAY',
            'badge_color' => '#000000',
            'show_discount_badge' => true,
        ],
        'cyber_monday' => [
            'name' => 'Cyber Monday',
            'discount_type' => 'percentage',
            'discount_value' => 25,
            'badge_text' => 'CYBER MONDAY',
            'badge_color' => '#3b82f6',
            'show_discount_badge' => true,
        ],
        'christmas' => [
            'name' => 'Natal',
            'discount_type' => 'percentage',
            'discount_value' => 20,
            'badge_text' => '🎄 NATAL',
            'badge_color' => '#22c55e',
            'show_discount_badge' => true,
        ],
        'new_year' => [
            'name' => 'Ano Novo',
            'discount_type' => 'percentage',
            'discount_value' => 15,
            'badge_text' => '🎆 ANO NOVO',
            'badge_color' => '#f59e0b',
            'show_discount_badge' => true,
        ],
        'summer_sale' => [
            'name' => 'Liquidação de Verão',
            'discount_type' => 'percentage',
            'discount_value' => 40,
            'badge_text' => 'LIQUIDAÇÃO',
            'badge_color' => '#ef4444',
            'show_discount_badge' => true,
        ],
        'flash_sale' => [
            'name' => 'Flash Sale',
            'discount_type' => 'percentage',
            'discount_value' => 50,
            'badge_text' => '⚡ FLASH SALE',
            'badge_color' => '#8b5cf6',
            'show_discount_badge' => true,
        ],
    ];

    /**
     * Usuário dono da campanha
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Produtos na campanha
     */
    public function products(): BelongsToMany
    {
        return $this->belongsToMany(ProductSheet::class, 'campaign_products', 'campaign_id', 'product_sheet_id')
            ->withPivot(['discount_type', 'discount_value', 'promotional_price', 'promo_margin', 'promo_margin_percent', 'is_profitable'])
            ->withTimestamps();
    }

    /**
     * Verifica se a campanha está ativa agora
     */
    public function isCurrentlyActive(): bool
    {
        if (!$this->is_active) {
            return false;
        }

        $now = Carbon::now();
        $today = $now->toDateString();
        
        // Verificar data
        if ($today < $this->start_date->toDateString() || $today > $this->end_date->toDateString()) {
            return false;
        }

        // Verificar hora se definida
        if ($this->start_time && $this->end_time) {
            $currentTime = $now->format('H:i:s');
            
            // Se for o primeiro dia, verificar hora de início
            if ($today === $this->start_date->toDateString() && $currentTime < $this->start_time) {
                return false;
            }
            
            // Se for o último dia, verificar hora de fim
            if ($today === $this->end_date->toDateString() && $currentTime > $this->end_time) {
                return false;
            }
        }

        return true;
    }

    /**
     * Calcula o preço promocional para um produto
     * COM PROTEÇÃO DE RENTABILIDADE
     */
    public function calculatePromotionalPrice(ProductSheet $product, ?array $override = null): float
    {
        $basePrice = (float) ($product->final_price ?? $product->sale_price);
        
        if ($basePrice <= 0) {
            return 0;
        }

        $discountType = $override['discount_type'] ?? $this->discount_type;
        $discountValue = (float) ($override['discount_value'] ?? $this->discount_value);

        $promoPrice = $basePrice;

        switch ($discountType) {
            case self::TYPE_PERCENTAGE:
                $promoPrice = $basePrice * (1 - ($discountValue / 100));
                break;
                
            case self::TYPE_FIXED:
                $promoPrice = $basePrice - $discountValue;
                break;
                
            case self::TYPE_PRICE_OVERRIDE:
                $promoPrice = $discountValue;
                break;
        }

        // === PROTEÇÃO DE RENTABILIDADE ===
        
        // 1. Aplicar preço mínimo da CAMPANHA se definido
        if ($this->min_price && $promoPrice < $this->min_price) {
            $promoPrice = (float) $this->min_price;
        }
        
        // 2. Aplicar preço mínimo do PRODUTO se definido (proteção individual)
        if ($product->min_price && $promoPrice < (float) $product->min_price) {
            $promoPrice = (float) $product->min_price;
        }
        
        // 3. NUNCA vender abaixo do CMV (Custo) - Proteção contra prejuízo
        $cmv = (float) ($product->cmv_total ?? 0);
        if ($cmv > 0 && $promoPrice < $cmv) {
            $promoPrice = $cmv; // Preço mínimo = custo (margem zero, sem prejuízo)
        }
        
        // 4. Aplicar margem mínima de segurança se configurada na campanha
        if ($this->min_margin_percent && $cmv > 0) {
            $minPriceWithMargin = $cmv * (1 + ($this->min_margin_percent / 100));
            if ($promoPrice < $minPriceWithMargin) {
                $promoPrice = $minPriceWithMargin;
            }
        }

        // Não pode ser negativo
        return max(0, round($promoPrice, 2));
    }
    
    /**
     * Verifica se o preço promocional gera lucro
     */
    public function isProfitable(ProductSheet $product): bool
    {
        $promoPrice = $this->calculatePromotionalPrice($product);
        $cmv = (float) ($product->cmv_total ?? 0);
        return $promoPrice > $cmv;
    }
    
    /**
     * Calcula a margem real durante a promoção
     */
    public function getPromotionalMargin(ProductSheet $product): array
    {
        $promoPrice = $this->calculatePromotionalPrice($product);
        $cmv = (float) ($product->cmv_total ?? 0);
        $originalPrice = (float) ($product->final_price ?? $product->sale_price);
        
        $promoMargin = $promoPrice - $cmv;
        $promoMarginPercent = $promoPrice > 0 ? ($promoMargin / $promoPrice) * 100 : 0;
        
        $originalMargin = $originalPrice - $cmv;
        $originalMarginPercent = $originalPrice > 0 ? ($originalMargin / $originalPrice) * 100 : 0;
        
        return [
            'promo_price' => $promoPrice,
            'cmv' => $cmv,
            'promo_margin' => round($promoMargin, 2),
            'promo_margin_percent' => round($promoMarginPercent, 1),
            'original_margin' => round($originalMargin, 2),
            'original_margin_percent' => round($originalMarginPercent, 1),
            'margin_reduction' => round($originalMarginPercent - $promoMarginPercent, 1),
            'is_profitable' => $promoMargin > 0,
            'is_protected' => $promoPrice >= $cmv,
        ];
    }

    /**
     * Calcula o percentual de desconto
     */
    public function getDiscountPercentage(float $originalPrice, float $promoPrice): float
    {
        if ($originalPrice <= 0) {
            return 0;
        }
        
        return round((($originalPrice - $promoPrice) / $originalPrice) * 100, 1);
    }

    /**
     * Retorna informações do badge para exibição
     */
    public function getBadgeInfo(float $originalPrice, float $promoPrice): ?array
    {
        if (!$this->show_discount_badge) {
            return null;
        }

        $discountPercent = $this->getDiscountPercentage($originalPrice, $promoPrice);
        
        return [
            'text' => $this->badge_text ?? "-{$discountPercent}%",
            'color' => $this->badge_color ?? '#ef4444',
            'discount_percent' => $discountPercent,
        ];
    }

    /**
     * Aplica a campanha a todos os produtos do usuário
     */
    public function applyToAllProducts(): int
    {
        if (!$this->apply_to_all_products) {
            return 0;
        }

        $products = ProductSheet::where('user_id', $this->user_id)
            ->where('is_active', true)
            ->get();

        $count = 0;
        foreach ($products as $product) {
            $promoPrice = $this->calculatePromotionalPrice($product);
            
            $this->products()->syncWithoutDetaching([
                $product->id => [
                    'promotional_price' => $promoPrice,
                ]
            ]);
            
            $count++;
        }

        return $count;
    }

    /**
     * Atualiza preços promocionais de todos os produtos da campanha
     */
    public function recalculateAllPrices(): void
    {
        foreach ($this->products as $product) {
            $override = null;
            if ($product->pivot->discount_type) {
                $override = [
                    'discount_type' => $product->pivot->discount_type,
                    'discount_value' => $product->pivot->discount_value,
                ];
            }
            
            $promoPrice = $this->calculatePromotionalPrice($product, $override);
            
            $this->products()->updateExistingPivot($product->id, [
                'promotional_price' => $promoPrice,
            ]);
        }
    }

    /**
     * Scope para campanhas do usuário
     */
    public function scopeOfUser($query, $userId)
    {
        return $query->where('user_id', $userId);
    }

    /**
     * Scope para campanhas ativas
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope para campanhas atuais (dentro do período)
     */
    public function scopeCurrent($query)
    {
        $now = Carbon::now();
        return $query->where('start_date', '<=', $now)
                     ->where('end_date', '>=', $now);
    }

    /**
     * Scope para campanhas futuras
     */
    public function scopeUpcoming($query)
    {
        return $query->where('start_date', '>', Carbon::now());
    }

    /**
     * Lista de presets disponíveis
     */
    public static function getPresets(): array
    {
        return self::PRESETS;
    }

    /**
     * Dias restantes da campanha
     */
    public function getDaysRemainingAttribute(): int
    {
        if (!$this->isCurrentlyActive()) {
            return 0;
        }
        
        return max(0, Carbon::now()->diffInDays($this->end_date, false));
    }

    /**
     * Status da campanha
     */
    public function getStatusAttribute(): string
    {
        if (!$this->is_active) {
            return 'inactive';
        }
        
        $now = Carbon::now();
        
        if ($now < $this->start_date) {
            return 'scheduled';
        }
        
        if ($now > $this->end_date) {
            return 'ended';
        }
        
        return 'active';
    }
}
