<?php
declare(strict_types=1);

namespace Autogedal\EanTools\Model\Spreadsheet;

use DateInterval;
use DateTimeInterface;
use OpenSpout\Common\Entity\Cell;
use OpenSpout\Common\Entity\Cell\ErrorCell;
use OpenSpout\Common\Entity\Cell\FormulaCell;

class XlsxCellValueConverter
{
    private const MAX_EXACT_INTEGER = 9007199254740992.0;

    public function convert(Cell $cell): string
    {
        if ($cell instanceof FormulaCell) {
            return $this->convertFormula($cell);
        }

        if ($cell instanceof ErrorCell) {
            return trim($cell->getRawValue());
        }

        return $this->convertValue($cell->getValue());
    }

    private function convertFormula(FormulaCell $cell): string
    {
        $computed = $cell->getComputedValue();

        return $computed === null ? trim($cell->getValue()) : $this->convertValue($computed);
    }

    private function convertValue(mixed $value): string
    {
        if ($value === null || $value instanceof DateInterval) {
            return '';
        }

        if ($value instanceof DateTimeInterface) {
            return $value->format('Y-m-d');
        }

        return $this->convertScalar($value);
    }

    private function convertScalar(bool|float|int|string $value): string
    {
        if (is_bool($value)) {
            return $value ? '1' : '0';
        }

        if (is_float($value)) {
            return $this->convertFloat($value);
        }

        return trim((string)$value);
    }

    private function convertFloat(float $value): string
    {
        return floor($value) === $value && abs($value) < self::MAX_EXACT_INTEGER
            ? sprintf('%.0f', $value)
            : (string)$value;
    }
}
