<?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;
use Illuminate\Database\Eloquent\SoftDeletes;

class ServiceSheet extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'user_id',
        'business_setting_id',
        'name',
        'code',
        'category',
        'description',
        'duration_minutes',
        'total_csv',
        'fixed_cost_portion',
        'calculated_price',
        'contribution_margin',
        'margin_percentage',
        'competitor_price',
        'min_price',
        'max_price',
        'premium_multiplier',
        'pricing_strategy',
        'target_margin',
        'psychological_pricing',
        'is_active',
    ];

    protected $casts = [
        'duration_minutes' => 'decimal:2',
        'total_csv' => 'decimal:2',
        'fixed_cost_portion' => 'decimal:2',
        'calculated_price' => 'decimal:2',
        'contribution_margin' => 'decimal:2',
        'margin_percentage' => 'decimal:2',
        'competitor_price' => 'decimal:2',
        'min_price' => 'decimal:2',
        'max_price' => 'decimal:2',
        'premium_multiplier' => 'decimal:4',
        'target_margin' => 'decimal:2',
        'psychological_pricing' => 'boolean',
        'is_active' => 'boolean',
    ];

    /**
     * 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 do serviço (insumos)
     */
    public function items(): HasMany
    {
        return $this->hasMany(ServiceSheetItem::class);
    }

    /**
     * Calcula o CSV (Custo do Serviço Vendido) somando todos os itens
     * 
     * @return float
     */
    public function calculateTotalCsv(): float
    {
        return $this->items->sum(function ($item) {
            return $item->unit_cost * $item->quantity_used;
        });
    }

    /**
     * Calcula o gasto fixo proporcional ao tempo do serviço
     * 
     * @return float
     */
    public function calculateFixedCostPortion(): float
    {
        $setting = $this->businessSetting;
        
        if (!$setting) {
            return 0;
        }
        
        return round($setting->fixed_cost_per_minute * $this->duration_minutes, 2);
    }

    /**
     * Calcula o preço de venda usando a fórmula de serviços:
     * Preço = (Gasto Fixo/Tempo + CSV) × Markup
     * 
     * @return float
     */
    public function calculatePrice(): float
    {
        $setting = $this->businessSetting;
        
        if (!$setting) {
            return 0;
        }
        
        $basePrice = $setting->calculateServicePrice(
            (float) $this->duration_minutes,
            (float) $this->total_csv
        );
        
        // Aplicar multiplicador premium
        $price = $basePrice * (float) ($this->premium_multiplier ?? 1);
        
        // Aplicar estratégia de preço baseada no competidor
        if ($this->competitor_price && $this->competitor_price > 0) {
            switch ($this->pricing_strategy) {
                case 'aggressive':
                    $strategicPrice = $this->competitor_price * 0.95;
                    $price = min($price, $strategicPrice);
                    break;
                case 'premium':
                    $strategicPrice = $this->competitor_price * 1.10;
                    $price = max($price, $strategicPrice);
                    break;
            }
        }
        
        // Aplicar limites min/max
        if ($this->min_price && $price < $this->min_price) {
            $price = (float) $this->min_price;
        }
        if ($this->max_price && $price > $this->max_price) {
            $price = (float) $this->max_price;
        }
        
        // Aplicar redondeo psicológico
        if ($this->psychological_pricing) {
            $price = $this->applyPsychologicalPricing($price);
        }
        
        return round($price, 2);
    }

    /**
     * Aplica redondeo psicológico (€26.04 → €25.99)
     */
    protected function applyPsychologicalPricing(float $price): float
    {
        $intPart = floor($price);
        $decimal = $price - $intPart;
        
        if ($decimal > 0 && $decimal <= 0.50) {
            return $intPart - 0.01;
        } elseif ($decimal > 0.50) {
            return $intPart + 0.99;
        }
        
        return $price - 0.01;
    }

    /**
     * Calcula a margem de contribuição
     * Margem = Preço - CSV - Gasto Fixo Proporcional - Deduções
     */
    public function calculateContributionMargin(): float
    {
        $price = (float) $this->calculated_price;
        $csv = (float) $this->total_csv;
        $fixedCost = (float) $this->fixed_cost_portion;
        
        $setting = $this->businessSetting;
        if (!$setting) {
            return 0;
        }
        
        // Para B2C, remover IVA do preço antes de calcular margem
        if ($setting->price_includes_tax) {
            $vatRate = (float) ($setting->vat_rate ?? 0);
            $price = $price / (1 + $vatRate / 100);
        }
        
        // Deduções variáveis
        $deductions = $price * ($setting->total_variable_costs / 100);
        
        return round($price - $csv - $fixedCost - $deductions, 2);
    }

    /**
     * Recalcula todos os valores e salva
     */
    public function recalculate(): self
    {
        $this->total_csv = $this->calculateTotalCsv();
        $this->fixed_cost_portion = $this->calculateFixedCostPortion();
        $this->calculated_price = $this->calculatePrice();
        $this->contribution_margin = $this->calculateContributionMargin();
        
        // Calcular margem percentual
        if ($this->calculated_price > 0) {
            $this->margin_percentage = round(
                ($this->contribution_margin / $this->calculated_price) * 100,
                2
            );
        } else {
            $this->margin_percentage = 0;
        }
        
        $this->save();
        
        return $this;
    }

    /**
     * Retorna o breakdown de custos para exibição
     */
    public function getCostBreakdownAttribute(): array
    {
        $setting = $this->businessSetting;
        $price = (float) $this->calculated_price;
        $csv = (float) $this->total_csv;
        $fixedCost = (float) $this->fixed_cost_portion;
        
        // Calcular valores
        $vatAmount = 0;
        $priceWithoutVat = $price;
        
        if ($setting && $setting->price_includes_tax) {
            $vatRate = (float) ($setting->vat_rate ?? 0);
            $priceWithoutVat = $price / (1 + $vatRate / 100);
            $vatAmount = $price - $priceWithoutVat;
        }
        
        $deductions = $setting ? $priceWithoutVat * ($setting->total_variable_costs / 100) : 0;
        
        return [
            'duration_minutes' => (float) $this->duration_minutes,
            'duration_hours' => round($this->duration_minutes / 60, 2),
            'csv' => $csv,
            'fixed_cost_portion' => $fixedCost,
            'base_cost' => $csv + $fixedCost,
            'markup' => $setting ? (float) $setting->markup_factor : 0,
            'price_without_vat' => round($priceWithoutVat, 2),
            'vat_amount' => round($vatAmount, 2),
            'vat_rate' => $setting && $setting->price_includes_tax ? (float) $setting->vat_rate : 0,
            'final_price' => $price,
            'deductions' => round($deductions, 2),
            'contribution_margin' => (float) $this->contribution_margin,
            'margin_percentage' => (float) $this->margin_percentage,
        ];
    }

    /**
     * Scope para buscar serviços de um usuário
     */
    public function scopeOfUser($query, $userId)
    {
        return $query->where('user_id', $userId);
    }

    /**
     * Scope para buscar serviços ativos
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }
}
