<?php

declare(strict_types=1);

namespace App\Services;

final class ArticlePricingService
{
    public function calculate(array $data): array
    {
        $prixAchat = $this->number($data['prix_achat_ht'] ?? 0);
        $coefficient = $this->number($data['coefficient'] ?? 0);
        $prixVente = $this->number($data['prix_vente_ht'] ?? 0);
        $tauxTva = $this->number($data['taux_tva'] ?? 20);

        $prixAchat = max(0, $prixAchat);
        $coefficient = max(0, $coefficient);
        $prixVente = max(0, $prixVente);
        $tauxTva = max(0, $tauxTva);

        /*
         * Règle officielle Phoenix :
         * - si un prix de vente est fourni, il est prioritaire ;
         * - le coefficient est alors recalculé ;
         * - sinon, le prix de vente est calculé depuis le coefficient.
         */
        if ($prixAchat > 0 && $prixVente > 0) {
            $coefficient = round(
                $prixVente / $prixAchat,
                3
            );
        } elseif ($prixAchat > 0 && $coefficient > 0) {
            $prixVente = round(
                $prixAchat * $coefficient,
                2
            );
        }

        $prixVenteTtc = round(
            $prixVente * (1 + ($tauxTva / 100)),
            2
        );

        $margeDh = round(
            $prixVente - $prixAchat,
            2
        );

        $margePourcentage = $prixVente > 0
            ? round(($margeDh / $prixVente) * 100, 2)
            : 0.0;

        return [
            'prix_achat_ht' => round($prixAchat, 2),
            'coefficient' => $coefficient,
            'prix_vente_ht' => round($prixVente, 2),
            'taux_tva' => round($tauxTva, 2),
            'prix_vente_ttc' => $prixVenteTtc,
            'marge_dh' => $margeDh,
            'marge_pourcentage' => $margePourcentage,
        ];
    }

    private function number(mixed $value): float
    {
        if (is_string($value)) {
            $value = str_replace(
                [' ', ','],
                ['', '.'],
                trim($value)
            );
        }

        return is_numeric($value)
            ? (float)$value
            : 0.0;
    }
}