<?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 BusinessSetting extends Model
{
    use HasFactory;

    protected $fillable = [
        'user_id',
        'currency',
        'name',
        'business_type',
        'employees_count',
        'hours_per_week',
        'working_days_per_week',
        'working_days_per_month',
        'productivity_rate',
        'monthly_revenue',
        'fixed_expenses',
        'tax_rate',
        'price_includes_tax',
        'vat_rate',
        'sales_commission',
        'card_fee',
        'other_variable_costs',
        'investment_rate',
        'profit_margin',
        'markup_factor',
        'is_active',
    ];

    protected $casts = [
        'business_type' => 'string',
        'employees_count' => 'integer',
        'hours_per_week' => 'decimal:2',
        'working_days_per_week' => 'integer',
        'working_days_per_month' => 'integer',
        'productivity_rate' => 'decimal:2',
        'monthly_revenue' => 'decimal:2',
        'fixed_expenses' => 'decimal:2',
        'tax_rate' => 'decimal:2',
        'price_includes_tax' => 'boolean',
        'vat_rate' => 'decimal:2',
        'sales_commission' => 'decimal:2',
        'card_fee' => 'decimal:2',
        'other_variable_costs' => 'decimal:2',
        'investment_rate' => 'decimal:2',
        'profit_margin' => 'decimal:2',
        'markup_factor' => 'decimal:4',
        'is_active' => 'boolean',
    ];

    /**
     * Derived attributes - calculated from hours_per_week
     */
    protected $appends = ['hours_per_day', 'productive_hours', 'fixed_cost_per_hour'];

    /**
     * Calcula horas por dia a partir de horas por semana
     * hours_per_day = hours_per_week / working_days_per_week
     */
    public function getHoursPerDayAttribute(): float
    {
        $hoursPerWeek = (float) ($this->hours_per_week ?? 40);
        $daysPerWeek = (int) ($this->working_days_per_week ?? 5);
        
        return $daysPerWeek > 0 ? round($hoursPerWeek / $daysPerWeek, 2) : 8;
    }

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

    /**
     * Fichas técnicas de produtos que usam esta configuração
     */
    public function productSheets(): HasMany
    {
        return $this->hasMany(ProductSheet::class);
    }

    /**
     * Fichas técnicas de serviços que usam esta configuração
     */
    public function serviceSheets(): HasMany
    {
        return $this->hasMany(ServiceSheet::class);
    }

    /**
     * Calcula as horas produtivas mensais
     * 
     * Formula baseada em horas por semana:
     * Horas Produtivas = Funcionários × (Horas/Semana × 4.33 semanas/mês) × Produtividade%
     * 
     * Ou usando dias do mês:
     * Horas Produtivas = Funcionários × (Horas/Semana / Dias/Semana × Dias/Mês) × Produtividade%
     * 
     * @return float
     */
    public function getProductiveHoursAttribute(): float
    {
        $employees = (int) ($this->employees_count ?? 1);
        $hoursPerWeek = (float) ($this->hours_per_week ?? 40);
        $daysPerWeek = (int) ($this->working_days_per_week ?? 5);
        $daysPerMonth = (int) ($this->working_days_per_month ?? 22);
        $productivity = (float) ($this->productivity_rate ?? 80) / 100;
        
        // Calcula horas por dia a partir de horas por semana
        $hoursPerDay = $daysPerWeek > 0 ? $hoursPerWeek / $daysPerWeek : 8;
        
        // Horas produtivas = funcionários × horas/dia × dias/mês × produtividade
        return round($employees * $hoursPerDay * $daysPerMonth * $productivity, 2);
    }

    /**
     * Calcula o gasto fixo por hora
     * Gasto Fixo/Hora = Despesas Fixas / Horas Produtivas
     * 
     * @return float
     */
    public function getFixedCostPerHourAttribute(): float
    {
        $productiveHours = $this->productive_hours;
        
        if ($productiveHours <= 0) {
            return 0;
        }
        
        return round((float) $this->fixed_expenses / $productiveHours, 2);
    }

    /**
     * Calcula o gasto fixo por minuto
     * 
     * @return float
     */
    public function getFixedCostPerMinuteAttribute(): float
    {
        return round($this->fixed_cost_per_hour / 60, 4);
    }

    /**
     * Calcula o preço de venda de um serviço
     * Preço = (Gasto Fixo/Hora × Duração em Horas + CSV) × Markup
     * 
     * Para B2C, ainda adiciona o IVA no final
     * 
     * @param float $durationMinutes Duração do serviço em minutos
     * @param float $csv Custo do Serviço Vendido (insumos)
     * @return float
     */
    public function calculateServicePrice(float $durationMinutes, float $csv): float
    {
        $markup = $this->markup_factor ?? $this->calculateMarkup();
        
        if ($markup <= 0) {
            return 0;
        }
        
        // Gasto fixo proporcional ao tempo do serviço
        $fixedCostPortion = $this->fixed_cost_per_minute * $durationMinutes;
        
        // Preço base = (Gasto Fixo + CSV) × Markup
        $priceWithoutTax = ($fixedCostPortion + $csv) * $markup;
        
        // Se B2C, adiciona IVA
        if ($this->price_includes_tax) {
            $vatRate = (float) ($this->vat_rate ?? 0);
            return round($priceWithoutTax * (1 + $vatRate / 100), 2);
        }
        
        return round($priceWithoutTax, 2);
    }

    /**
     * Calcula o percentual de despesas fixas sobre a receita
     * 
     * @return float
     */
    public function getFixedExpensesRateAttribute(): float
    {
        if ($this->monthly_revenue <= 0) {
            return 0;
        }
        
        return round(($this->fixed_expenses / $this->monthly_revenue) * 100, 2);
    }

    /**
     * Calcula o total de custos variáveis (sem CMV)
     * Para B2C (price_includes_tax=true), o tax_rate NÃO entra aqui pois é adicionado ao final
     * Para B2B (price_includes_tax=false), o tax_rate é uma dedução do preço
     * 
     * @return float
     */
    public function getTotalVariableCostsAttribute(): float
    {
        $costs = $this->sales_commission + 
                 $this->card_fee + 
                 $this->other_variable_costs;
        
        // Se B2B (preço NÃO inclui imposto), adiciona tax_rate como custo
        if (!$this->price_includes_tax) {
            $costs += $this->tax_rate;
        }
        
        return $costs;
    }

    /**
     * Calcula o fator de Markup usando a fórmula:
     * Markup = 1 / (1 - (Despesas Fixas % + Custos Variáveis % + Investimento % + Lucro %))
     * 
     * @return float
     */
    public function calculateMarkup(): float
    {
        // Converter percentuais para decimais
        $fixedExpensesRate = $this->fixed_expenses_rate / 100;
        $variableCosts = $this->total_variable_costs / 100;
        $investmentRate = $this->investment_rate / 100;
        $profitMargin = $this->profit_margin / 100;
        
        // Total de deduções
        $totalDeductions = $fixedExpensesRate + $variableCosts + $investmentRate + $profitMargin;
        
        // Verificar se é possível calcular (não pode ser >= 100%)
        if ($totalDeductions >= 1) {
            return 0; // Markup inválido - deduções >= 100%
        }
        
        // Fórmula: Markup = 1 / (1 - deduções)
        $markup = 1 / (1 - $totalDeductions);
        
        return round($markup, 4);
    }

    /**
     * Recalcula e salva o markup
     * 
     * @return float
     */
    public function recalculateMarkup(): float
    {
        $this->markup_factor = $this->calculateMarkup();
        $this->save();
        
        return $this->markup_factor;
    }

    /**
     * Calcula o preço de venda para um CMV dado
     * 
     * B2B (price_includes_tax=false): Preço = CMV × Markup (imposto já está nas deduções)
     * B2C (price_includes_tax=true): Preço = CMV × Markup × (1 + VAT%) (imposto adicionado ao final)
     * 
     * @param float $cmv Custo da Mercadoria Vendida
     * @return float
     */
    public function calculateSalePrice(float $cmv): float
    {
        $markup = $this->markup_factor ?? $this->calculateMarkup();
        
        if ($markup <= 0) {
            return 0;
        }
        
        $priceWithoutTax = $cmv * $markup;
        
        // Se B2C (preço inclui imposto), adiciona o IVA/VAT ao preço final
        if ($this->price_includes_tax) {
            $vatRate = (float) ($this->vat_rate ?? 0);
            return round($priceWithoutTax * (1 + $vatRate / 100), 2);
        }
        
        return round($priceWithoutTax, 2);
    }

    /**
     * Calcula o preço SEM impostos para um CMV dado
     * Útil para mostrar o preço base antes do IVA
     * 
     * @param float $cmv Custo da Mercadoria Vendida
     * @return float
     */
    public function calculatePriceWithoutTax(float $cmv): float
    {
        $markup = $this->markup_factor ?? $this->calculateMarkup();
        
        if ($markup <= 0) {
            return 0;
        }
        
        return round($cmv * $markup, 2);
    }

    /**
     * Extrai o valor do IVA de um preço final (B2C)
     * 
     * @param float $finalPrice Preço final com IVA
     * @return float
     */
    public function extractVat(float $finalPrice): float
    {
        if (!$this->price_includes_tax) {
            return 0;
        }
        
        $vatRate = (float) ($this->vat_rate ?? 0);
        if ($vatRate <= 0) {
            return 0;
        }
        
        $priceWithoutVat = $finalPrice / (1 + $vatRate / 100);
        return round($finalPrice - $priceWithoutVat, 2);
    }

    /**
     * Retorna o breakdown do Markup para exibição
     * 
     * @return array
     */
    public function getMarkupBreakdownAttribute(): array
    {
        return [
            'fixed_expenses_rate' => $this->fixed_expenses_rate,
            'tax_rate' => (float) $this->tax_rate,
            'price_includes_tax' => (bool) $this->price_includes_tax,
            'vat_rate' => (float) ($this->vat_rate ?? 21),
            'sales_commission' => (float) $this->sales_commission,
            'card_fee' => (float) $this->card_fee,
            'other_variable_costs' => (float) $this->other_variable_costs,
            'total_variable_costs' => $this->total_variable_costs,
            'investment_rate' => (float) $this->investment_rate,
            'profit_margin' => (float) $this->profit_margin,
            'total_deductions' => $this->fixed_expenses_rate + $this->total_variable_costs + $this->investment_rate + $this->profit_margin,
            'markup_factor' => (float) ($this->markup_factor ?? $this->calculateMarkup()),
        ];
    }

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

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