<?php
namespace Incoviba\Service;

use DateTimeInterface;
use DateTimeImmutable;
use DateMalformedStringException;
use function PHPUnit\Framework\countOf;

class Valor
{
    public function __construct(protected UF $ufService) {}

    public function clean(string|float|int $value): float
    {
        if (!is_string($value)) {
            return (float) $value;
        }
        if ((int) $value == $value) {
            return (float) $value;
        }

        if ($this->isUS($value)) {
            return $this->formatUS($value);
        }
        return $this->formatCL($value);
    }
    public function toPesos(string $value, null|string|DateTimeInterface $date = null, bool $force = false): int
    {
        $date = $this->getDateTime($date);
        if ($this->inUF($value) or $force) {
            return round($value * $this->ufService->get($date));
        }
        return (int) $value;
    }
    public function toUF(string $value, null|string|DateTimeInterface $date = null, bool $force = false): float
    {
        $date = $this->getDateTime($date);
        if ($this->inUF($value) and !$force) {
            return (float) $value;
        }
        return $value / $this->ufService->get($date);
    }

    protected function getDateTime(null|string|DateTimeInterface $date): DateTimeInterface
    {
        if ($date === null) {
            return new DateTimeImmutable();
        }
        if (is_string($date)) {
            try {
                return new DateTimeImmutable($date);
            } catch (DateMalformedStringException) {
                return new DateTimeImmutable();
            }
        }
        return $date;
    }

    protected function isUS(string $value): bool
    {
        /*
         * Chile
         * 1.000.000,00
         * 10000,000
         * 10,53
         * 1.000,00
         * 1.000 imposible! se asume US si # antes de . < 10
         *
         * 1,000,000.00
         * 10000.00
         * 1,000.000
         * 10.53
         * 1,000 imposible! se asume CL
         */
        if (str_contains($value, '.')) {
            $parts = explode('.', $value);
            if (count($parts) > 2) {    // 1.000.000 || 1.000.000,00
                return false;
            }
            if (strlen($parts[0]) > 3) { // 1000.000 || 1,000.000
                return true;
            }
            if (strlen($parts[1]) < 3) { // #####.00
                return true;
            }
            if (str_contains($value, ',')) {
                if (strpos($value, ',') > strpos($value, '.')) { // 1.000,000
                    return false;
                }
                return true; // 1,000.000
            }
            if ((int) $parts[0] < 10) { // 1.000
                return true;
            }
            return false;
        }
        return true;
    }
    protected function formatCL(string $value): float
    {
        return (float) str_replace(',', '.', (str_replace('.', '', $value)));
    }
    protected function formatUS(string $value): float
    {
        return (float) str_replace(',', '', $value);
    }
    protected function inUF(string|int|float $value, float $check = 10000): bool
    {
        if (!is_string($value)) {
            if ($value >= $check) { // Valor arbitrario mayor que el cual no es UF
                return false;
            }
            return is_float($value);
        }
        $cleaned = $this->clean($value);
        return round($cleaned) !== $cleaned;
    }
}
