<?php

namespace Myvetshop\Module\Clinique\Api\Crokit\Normalizer;

use Myvetshop\Module\Clinique\Api\Crokit\Dto\CrokitRecommandation;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

class CrokitRecommandationNormalizer implements DenormalizerInterface
{
    /**
     * @param array<mixed> $data
     */
    protected static function stringToInt(array $data, string $key): ?int
    {
        $rawValue = $data[$key] ?? '';

        if (\is_string($rawValue)) {
            return empty($rawValue) ? null : (int) $rawValue;
        } elseif (\is_int($rawValue)) {
            return $rawValue;
        } elseif (\is_float($rawValue)) {
            return (int) \floor($rawValue);
        }

        throw new \Exception('Invalid data : ' . $key);
    }

    /**
     * @param array<mixed> $data
     */
    protected static function stringToFloat(array $data, string $key): float
    {
        $rawValue = $data[$key] ?? '';

        if (empty($rawValue)) {
            throw new \Exception('Invalid data : ' . $key);
        } elseif (\is_string($rawValue)) {
            return \round((float) $rawValue, 2);
        } elseif (\is_int($rawValue)) {
            return (float) $rawValue;
        } elseif (\is_float($rawValue)) {
            return \floor($rawValue);
        }

        throw new \Exception('Invalid data : ' . $key);
    }

    /**
     * @param array<mixed> $data
     */
    protected static function filteredString(array $data, string $key): ?string
    {
        $rawValue = $data[$key] ?? '';

        if (!\is_string($rawValue)) {
            throw new \Exception('Invalid data : ' . $key);
        }

        return empty($rawValue) ? null : $rawValue;
    }

    /**
     * @param array<mixed> $data
     * @param array<mixed> $context
     *
     * @return CrokitRecommandation
     */
    public function denormalize($data, $type, $format = null, array $context = [])
    {
        $ret = new CrokitRecommandation();

        $denormalized = new CrokitRecommandation();

        if (!\is_string($data['date'])) {
            throw new \Exception('Invalid raw date format');
        }

        $date = \DateTimeImmutable::createFromFormat('d-m-Y', $data['date']);
        if (false === $date) {
            throw new \Exception('Invalid date : ' . $data['date']);
        }

        $denormalized->date = $date;
        $denormalized->code = $data['code'];
        $denormalized->petname = $data['petname'];
        $denormalized->esp = $data['esp'];
        $denormalized->race = $data['race'];
        $denormalized->sex = $data['sex'];
        $denormalized->act = $data['act'];
        $denormalized->age = $data['age'];
        $denormalized->dob = $data['dob'];
        $denormalized->stadePhysio = $data['stadePhysio'];
        $denormalized->patho = $data['patho'];
        $denormalized->actualw = self::stringToFloat($data, 'actualw');
        $denormalized->idealw = self::stringToFloat($data, 'idealw');
        $denormalized->be = self::stringToInt($data, 'be');
        $denormalized->nbrAliment = \intval($data['nbrAliment']);
        $denormalized->productIDmvs1 = \intval($data['productIDmvs1']);
        $denormalized->productIDmvs2 = self::stringToInt($data, 'productIDmvs2');
        $denormalized->productIDmvs3 = self::stringToInt($data, 'productIDmvs3');
        $denormalized->qteAliment1 = \intval($data['qteAliment1']);
        $denormalized->qteAliment2 = self::stringToInt($data, 'qteAliment2');
        $denormalized->qteAliment3 = self::stringToInt($data, 'qteAliment3');
        $denormalized->transition12 = self::stringToInt($data, 'transition12');
        $denormalized->transition23 = self::stringToInt($data, 'transition23');

        return $denormalized;
    }

    public function supportsDenormalization($data, $type, $format = null)
    {
        return \is_array($data) && CrokitRecommandation::class === $type;
    }
}
