<?php

namespace App\Services;

/**
 * Convert numbers to French words (Tunisian Dinar format)
 * Used for: "ARRETEE LA PRESENTE A LA SOMME DE: ..."
 */
class NumberToWordsService
{
    private array $units = ['', 'un', 'deux', 'trois', 'quatre', 'cinq', 'six', 'sept', 'huit', 'neuf'];
    private array $teens = ['dix', 'onze', 'douze', 'treize', 'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit', 'dix-neuf'];
    private array $tens = ['', 'dix', 'vingt', 'trente', 'quarante', 'cinquante', 'soixante', 'soixante', 'quatre-vingt', 'quatre-vingt'];

    /**
     * Convert decimal amount to words in Tunisian Dinar format
     * Example: 467.48 -> "QUATRE CENT SOIXANTE SEPT DINARS ET QUATRE CENT QUATRE VINGT MILLIMES"
     */
    public function toWords(float $amount, string $currency = 'TND'): string
    {
        $whole = (int) $amount;
        $cents = (int) round(($amount - $whole) * 1000); // Millimes for TND

        $result = '';

        if ($whole > 0) {
            $result .= strtoupper($this->convertNumber($whole));
            $result .= ' ' . ($whole == 1 ? 'DINAR' : 'DINARS');
        }

        if ($cents > 0) {
            if ($whole > 0) {
                $result .= ' ET ';
            }
            $result .= strtoupper($this->convertNumber($cents));
            $result .= ' ' . ($cents == 1 ? 'MILLIME' : 'MILLIMES');
        }

        if ($whole == 0 && $cents == 0) {
            $result = 'ZERO DINARS';
        }

        return $result;
    }

    private function convertNumber(int $number): string
    {
        if ($number == 0) return 'zéro';
        if ($number < 10) return $this->units[$number];
        if ($number < 20) return $this->teens[$number - 10];
        if ($number < 100) return $this->convertTens($number);
        if ($number < 1000) return $this->convertHundreds($number);
        if ($number < 1000000) return $this->convertThousands($number);
        if ($number < 1000000000) return $this->convertMillions($number);

        return 'nombre trop grand';
    }

    private function convertTens(int $number): string
    {
        $ten = (int) ($number / 10);
        $unit = $number % 10;

        if ($number < 70) {
            return $this->tens[$ten] . ($unit > 0 ? '-' . $this->units[$unit] : '');
        }
        if ($number < 80) {
            return 'soixante' . ($unit > 0 ? '-' . $this->teens[$unit] : '');
        }
        return 'quatre-vingt' . ($unit > 0 ? '-' . $this->units[$unit] : '');
    }

    private function convertHundreds(int $number): string
    {
        $hundred = (int) ($number / 100);
        $rest = $number % 100;

        $result = '';
        if ($hundred == 1) {
            $result = 'cent';
        } else {
            $result = $this->units[$hundred] . ' cent';
        }

        if ($rest > 0) {
            $result .= ' ' . $this->convertNumber($rest);
        }

        return $result;
    }

    private function convertThousands(int $number): string
    {
        $thousand = (int) ($number / 1000);
        $rest = $number % 1000;

        $result = '';
        if ($thousand == 1) {
            $result = 'mille';
        } else {
            $result = $this->convertNumber($thousand) . ' mille';
        }

        if ($rest > 0) {
            $result .= ' ' . $this->convertNumber($rest);
        }

        return $result;
    }

    private function convertMillions(int $number): string
    {
        $million = (int) ($number / 1000000);
        $rest = $number % 1000000;

        $result = $this->convertNumber($million) . ' million';
        if ($million > 1) $result .= 's';

        if ($rest > 0) {
            $result .= ' ' . $this->convertNumber($rest);
        }

        return $result;
    }
}
