<?php

namespace AutoAdmin\Bundle\Admin\Helper;

use AutoAdmin\Bundle\Admin\Configuration\ConfigManager;
use AutoAdmin\Bundle\Admin\Router\AdminRouter;
use AutoAdmin\Bundle\Content\Entity\AbstractContent;
use AutoAdmin\Bundle\Content\Model\ContentInterface;
use AutoAdmin\Bundle\Content\Model\NameInterface;
use AutoAdmin\Bundle\Content\Model\TitleInterface;
use AutoAdmin\Bundle\Content\Model\TranslatableInterface;
use Countable;
use DateTimeInterface;
use DateTimeZone;
use ReflectionClass;

class StringifierHelper
{
    public function __construct(
        protected AdminRouter $router,
        protected ConfigManager $configManager,
        protected UserTimezoneProvider $timezoneProvider,
    )
    {
    }

    public function stringify($value, bool $isId = false): string
    {
        if (is_float($value)) {
            return '<div class="text-center p-2"><span>'.$value.'</span></div>';
        }

        if (is_int($value)) {
            return sprintf(
                '<div class="text-center p-2"><span class="%s">%s</span></div>',
                $isId ? 'font-weight-bold' : '',
                $value
            );
        }

        if (is_bool($value)) {
            return sprintf(
                '<div class="text-center p-2"><i class="fa %s %s"></i></div>',
                $value ? 'fa-check' : 'fa-times',
                $value ? 'text-success' : 'text-danger'
            );
        }

        if (empty($value)) {
            return '<div class="p-2"><span class="badge badge-warning">VIDE</span></div>';
        }

        // Countable : array & collection

        if (is_countable($value)) {

            if (is_array($value)) {
                if ($this->isInlinableArray($value)) {
                    return $this->inlineArray($value);
                } else {
                    return '<div class="p-2"><span>'.count($value).' elements</span></div>';
                }
            }

            if ($value instanceof Countable) {
                return '<div class="p-2"><span>'.$value->count().' elements</span></div>';
            }
        }

        // String - Don't forget to secure
        if (is_string($value)) {
            // Securize
            $value = htmlspecialchars($value);

            // Is URL
            if (filter_var($value, FILTER_VALIDATE_URL) !== false) {
                return '<a href="' . $value . '">' . $value . '</a>';
            }

            // Is Email
            if (filter_var($value, FILTER_VALIDATE_EMAIL) !== false) {
                return '<a href="mailto:' . $value . '">' . $value . '</a>';
            }

            // Classical string
            $titleValue = str_replace(['\'', '"'], '', $value);

            return '<div class="p-2"><span title="'.$titleValue.'">'.$value.'</span></div>';
        }

        // Objects
        if (is_object($value)) {
            if ($value instanceof DateTimeInterface) {
                $date = clone $value;
                $date->setTimezone(new DateTimeZone($this->timezoneProvider->getUserTimezone()));

                return '<div class="p-2"><span>'.$date->format('d/m/y H:i').'</span></div>';
            }

            if ($value instanceof AbstractContent) {
                return $this->getContentTitledLink($value);
            }

            $refl = new ReflectionClass($value);

            if ($refl->hasMethod('__toString')) {
                return (string)$value;
            }

            return '<div class="p-2"><span class="text-warning">L\'objet ne peut pas être convertit en texte</span></div>';
        }

        return '<div class="p-2"><span class="text-danger">Valeur non reconnue</span></div>';
    }

    protected function getContentTitledLink(ContentInterface $content): string
    {
        $entityTitle = '#'.$content->getId();
        if ($content instanceof TranslatableInterface) {
            $translation = $content->getCurrentTranslation();
            if (!empty($translation) && $translation instanceof TitleInterface) {
                $entityTitle = $translation->getTitle();
            } elseif (!empty($translation) && $translation instanceof NameInterface) {
                $entityTitle = $translation->getName();
            }
        }

        $url = $this->router->generate($content, 'update');

        return sprintf('<a href="%s">%s</a>', $url, $entityTitle);
    }

    protected function isInlinableArray(array $array): bool
    {
        foreach ($array as $k => $item) {
            if (!is_numeric($k) || !is_scalar($item)) {
                return false;
            }
        }

        return true;
    }

    protected function inlineArray(array $array): string
    {
        $innerValue = implode(' ; ', array_slice($array, 0, 5)).(count($array) > 10 ? ', […]' : '');

        $title = strip_tags($innerValue);
        $title = substr($title, strlen('Tableau '));
        $title = ''.count($array).' items : '.$title;

        return '<span title="'.$title.'">'.$innerValue.'</span>';
    }
}
