<?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\HasMany;

class ProductSheet extends Model
{
    use HasFactory;

    protected $fillable = [
        'user_id',
        'business_setting_id',
        'name',
        'sku',
        'description',
        'category',
        'base_volume_ml',
        'standard_portion_ml',
        'currency',
        'cmv_total',
        'sale_price',
        'markup_used',
        'contribution_margin',
        'is_active',
        // Strategic pricing fields
        'competitor_price',
        'min_price',
        'max_price',
        'premium_multiplier',
        'price_strategy',
        'psychological_rounding',
        'target_margin_percent',
        'final_price',
        'real_margin_percent',
    ];

    protected $casts = [
        'cmv_total' => 'decimal:2',
        'sale_price' => 'decimal:2',
        'markup_used' => 'decimal:4',
        'contribution_margin' => 'decimal:2',
        'is_active' => 'boolean',
        // Strategic pricing casts
        'competitor_price' => 'decimal:2',
        'min_price' => 'decimal:2',
        'max_price' => 'decimal:2',
        'premium_multiplier' => 'decimal:2',
        'psychological_rounding' => 'boolean',
        'target_margin_percent' => 'decimal:2',
        'final_price' => 'decimal:2',
        'real_margin_percent' => 'decimal:2',
    ];

    // Price strategies
    const STRATEGY_AGGRESSIVE = 'aggressive';
    const STRATEGY_NEUTRAL = 'neutral';
    const STRATEGY_PREMIUM = 'premium';

    /**
     * Relacionamento com usuário
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Relacionamento com configuração de negócio
     */
    public function businessSetting(): BelongsTo
    {
        return $this->belongsTo(BusinessSetting::class);
    }

    /**
     * Itens/componentes de custo desta ficha técnica
     */
    public function items(): HasMany
    {
        return $this->hasMany(ProductSheetItem::class)->orderBy('sort_order');
    }

    /**
     * Variantes de venda do produto (ex: Garrafa, Taça, Meia Taça, Degustar)
     */
    public function variants(): HasMany
    {
        return $this->hasMany(ProductVariant::class)->orderBy('sort_order');
    }

    /**
     * Recalcula o CMV total baseado nos itens
     * 
     * @return float
     */
    public function recalculateCmv(): float
    {
        $this->cmv_total = $this->items()->sum('unit_cost');
        $this->save();
        
        return $this->cmv_total;
    }

    /**
     * Calcula e atualiza o preço de venda usando o Markup da configuração
     * 
     * @param BusinessSetting|null $businessSetting
     * @return float
     */
    public function calculateSalePrice(?BusinessSetting $businessSetting = null): float
    {
        $setting = $businessSetting ?? $this->businessSetting;
        
        if (!$setting) {
            return 0;
        }
        
        $markup = $setting->markup_factor ?? $setting->calculateMarkup();
        
        if ($markup <= 0) {
            return 0;
        }
        
        $this->markup_used = $markup;
        $this->sale_price = round($this->cmv_total * $markup, 2);
        $this->contribution_margin = $this->sale_price - $this->cmv_total;
        $this->save();
        
        return $this->sale_price;
    }

    /**
     * Retorna a margem de contribuição percentual
     * 
     * @return float
     */
    public function getContributionMarginPercentAttribute(): float
    {
        if ($this->sale_price <= 0) {
            return 0;
        }
        
        return round(($this->contribution_margin / $this->sale_price) * 100, 2);
    }

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

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

    /**
     * Scope para buscar por categoria
     */
    public function scopeByCategory($query, $category)
    {
        return $query->where('category', $category);
    }

    /**
     * Calcula o preço final aplicando estratégias de precificação
     * 
     * @return float
     */
    public function calculateFinalPrice(): float
    {
        // Começar com o preço base (markup)
        $basePrice = (float) $this->sale_price;
        
        if ($basePrice <= 0) {
            return 0;
        }

        $finalPrice = $basePrice;

        // 1. Aplicar multiplicador premium
        $premiumMultiplier = (float) ($this->premium_multiplier ?? 1.0);
        $finalPrice = $finalPrice * $premiumMultiplier;

        // 2. Aplicar estratégia de preço baseada no concorrente
        if ($this->competitor_price && $this->competitor_price > 0) {
            $competitorPrice = (float) $this->competitor_price;
            
            switch ($this->price_strategy) {
                case self::STRATEGY_AGGRESSIVE:
                    // 5% abaixo do concorrente
                    $targetPrice = $competitorPrice * 0.95;
                    $finalPrice = min($finalPrice, $targetPrice);
                    break;
                    
                case self::STRATEGY_PREMIUM:
                    // 10% acima do concorrente
                    $targetPrice = $competitorPrice * 1.10;
                    $finalPrice = max($finalPrice, $targetPrice);
                    break;
                    
                case self::STRATEGY_NEUTRAL:
                default:
                    // Manter preço calculado, mas não muito diferente do concorrente
                    break;
            }
        }

        // 3. Aplicar margem alvo específica se definida
        if ($this->target_margin_percent !== null && $this->target_margin_percent > 0) {
            $targetMargin = (float) $this->target_margin_percent / 100;
            $cmv = (float) $this->cmv_total;
            // Preço = CMV / (1 - margem)
            $targetPrice = $cmv / (1 - $targetMargin);
            $finalPrice = $targetPrice;
        }

        // 4. Aplicar limites min/max
        if ($this->min_price && $finalPrice < $this->min_price) {
            $finalPrice = (float) $this->min_price;
        }
        if ($this->max_price && $finalPrice > $this->max_price) {
            $finalPrice = (float) $this->max_price;
        }

        // 5. Aplicar arredondamento psicológico
        if ($this->psychological_rounding) {
            $finalPrice = $this->applyPsychologicalRounding($finalPrice);
        }

        // Salvar resultado
        $this->final_price = round($finalPrice, 2);
        $this->real_margin_percent = $this->calculateRealMargin($this->final_price);
        $this->save();

        return $this->final_price;
    }

    /**
     * Aplica arredondamento psicológico ao preço
     * Ex: 26.04 -> 25.99, 135.41 -> 134.99
     * 
     * @param float $price
     * @return float
     */
    protected function applyPsychologicalRounding(float $price): float
    {
        if ($price < 10) {
            // Preços baixos: arredondar para .99
            return floor($price) + 0.99;
        } elseif ($price < 100) {
            // Preços médios: arredondar para X9.99
            $tens = floor($price / 10) * 10;
            $remainder = $price - $tens;
            if ($remainder >= 5) {
                return $tens + 9.99;
            } else {
                return $tens - 0.01;
            }
        } else {
            // Preços altos: arredondar para XX9.99 ou XX4.99
            $hundreds = floor($price / 100) * 100;
            $remainder = $price - $hundreds;
            if ($remainder >= 75) {
                return $hundreds + 99.99;
            } elseif ($remainder >= 25) {
                return $hundreds + 49.99;
            } else {
                return $hundreds - 0.01;
            }
        }
    }

    /**
     * Calcula a margem real baseada no preço final
     * 
     * @param float $finalPrice
     * @return float
     */
    protected function calculateRealMargin(float $finalPrice): float
    {
        if ($finalPrice <= 0) {
            return 0;
        }
        
        $cmv = (float) $this->cmv_total;
        $margin = (($finalPrice - $cmv) / $finalPrice) * 100;
        
        return round($margin, 2);
    }

    /**
     * Retorna comparação com concorrente
     * 
     * @return array|null
     */
    public function getCompetitorComparisonAttribute(): ?array
    {
        if (!$this->competitor_price || $this->competitor_price <= 0) {
            return null;
        }

        $finalPrice = (float) ($this->final_price ?? $this->sale_price);
        $competitorPrice = (float) $this->competitor_price;
        $difference = $finalPrice - $competitorPrice;
        $percentDiff = (($finalPrice - $competitorPrice) / $competitorPrice) * 100;

        return [
            'competitor_price' => $competitorPrice,
            'our_price' => $finalPrice,
            'difference' => round($difference, 2),
            'percent_difference' => round($percentDiff, 2),
            'position' => $difference > 0 ? 'above' : ($difference < 0 ? 'below' : 'equal'),
        ];
    }

    /**
     * Lista de estratégias disponíveis
     */
    public static function getStrategies(): array
    {
        return [
            self::STRATEGY_AGGRESSIVE => 'Agressivo (5% abaixo do concorrente)',
            self::STRATEGY_NEUTRAL => 'Neutro (preço calculado)',
            self::STRATEGY_PREMIUM => 'Premium (10% acima do concorrente)',
        ];
    }
}
