<?php
/**
 * ShippingCalculator
 * 
 * Classe responsável por cálculos de peso e cubagem.
 * Implementa algoritmo de Bin Packing simplificado.
 * 
 * @package Shipping
 */

namespace Shipping;

class ShippingCalculator
{
    // Peso volumétrico: divisor padrão (PAC/SEDEX usa 6000)
    private int $volumetricDivisor = 6000;
    
    /**
     * Calcula peso real total e peso volumétrico dos itens
     * 
     * @param array $items Array de produtos com peso/dimensões
     * @return array [weight => peso real, volumetric_weight => peso cúbico, billable_weight => peso cobrado]
     */
    public function calculateTotalWeight(array $items): array
    {
        $totalRealWeight = 0;
        $totalVolume = 0;
        
        foreach ($items as $item) {
            $qty = $item['quantity'] ?? 1;
            
            // Peso real (default 0.3kg se não informado)
            $weight = floatval($item['weight'] ?? 0.3);
            $totalRealWeight += $weight * $qty;
            
            // Volume (default 10x10x10cm se não informado)
            $height = floatval($item['height'] ?? 10);
            $width = floatval($item['width'] ?? 10);
            $length = floatval($item['length'] ?? 10);
            $volume = ($height * $width * $length) * $qty;
            $totalVolume += $volume;
        }
        
        // Peso volumétrico (cm³ / divisor)
        $volumetricWeight = $totalVolume / $this->volumetricDivisor;
        
        // Peso cobrado é o maior entre real e volumétrico
        $billableWeight = max($totalRealWeight, $volumetricWeight);
        
        return [
            'weight' => round($totalRealWeight, 3),
            'volumetric_weight' => round($volumetricWeight, 3),
            'billable_weight' => round($billableWeight, 3),
            'total_volume_cm3' => round($totalVolume, 2)
        ];
    }
    
    /**
     * Calcula dimensões de uma "caixa virtual" para o conjunto de itens
     * Algoritmo simplificado: raiz cúbica do volume total
     * 
     * @param array $items Array de produtos
     * @return array [height, width, length] em cm
     */
    public function calculateVirtualBox(array $items): array
    {
        $totalVolume = 0;
        $maxHeight = 0;
        $maxWidth = 0;
        $maxLength = 0;
        
        foreach ($items as $item) {
            $qty = $item['quantity'] ?? 1;
            $height = floatval($item['height'] ?? 10);
            $width = floatval($item['width'] ?? 10);
            $length = floatval($item['length'] ?? 10);
            
            $totalVolume += ($height * $width * $length) * $qty;
            
            // Guardar as maiores dimensões individuais
            $maxHeight = max($maxHeight, $height);
            $maxWidth = max($maxWidth, $width);
            $maxLength = max($maxLength, $length);
        }
        
        // Raiz cúbica para dimensão aproximada
        $cubeRoot = pow($totalVolume, 1/3);
        
        // A caixa virtual usa a raiz cúbica mas respeita dimensões mínimas
        return [
            'height' => max(ceil($cubeRoot), $maxHeight),
            'width' => max(ceil($cubeRoot), $maxWidth),
            'length' => max(ceil($cubeRoot), $maxLength)
        ];
    }
    
    /**
     * Define o divisor volumétrico
     * @param int $divisor
     */
    public function setVolumetricDivisor(int $divisor): void
    {
        $this->volumetricDivisor = $divisor;
    }
}
