<?php

namespace AutoAdmin\Bundle\DependencyInjection\Configuration;

use AutoAdmin\Bundle\Content\DependencyInjection\Exception\InvalidConfigurationException;
use AutoAdmin\Bundle\Content\Slug\EntitySlug;
use RuntimeException;

class RawConfigurationFixer
{
    public function fixRawConfigs(array $configs): array
    {
        $configs = $this->fixAdmin($configs);
        $configs = $this->fixContent($configs);

        return $configs;
    }


    /**
     * If multiple config files are used, then we lose keys in subsequent config files (for entities index for example)
     * So: manually report every entity to first config file and delete it from its origin,
     * this way we can maintain keys and their uniqueness
     */
    private function fixAdmin(array $configs): array
    {
        if (empty($configs[0])) {
            return $configs;
        }

        $mergeConfig = [];

        foreach ($configs as $idx => $config) {
            if (empty($config['admin']['entities'])) {
                continue;
            }
            foreach ($config['admin']['entities'] as $k => $entity) {
                if (isset($mergeConfig[$k])) {
                    throw new RuntimeException(sprintf('Admin entity key "%s" is already taken.', $k));
                }

                // if class is not explicit, set it using array keys
                if (!isset($entity['class']) || $entity['class'] === null) {
                    $entity['class'] = $k;
                }

                $mergeConfig[$k] = $entity;
                unset($configs[$idx + 1]['admin']['entities'][$k]);
            }
        }

        $configs[0]['admin']['entities'] = $mergeConfig;

        return $configs;
    }

    private function fixContent(array $configs): array
    {
        $existingEntityNames = [];
        foreach ($configs as $i => $rawConfig) {
            if (!empty($rawConfig['content'])) {
                $processedContents = [];
                $processedSlugs = [];
                // configs can be multiple yaml with either admin or content as first sub-level
                $config = $rawConfig['content'];

                foreach ($config['contents'] as $key => $entityConfig) {
                    $slug = $entityConfig['slug'] ?? EntitySlug::getSlug($key);

                    if (!class_exists($key)) {
                        throw new InvalidConfigurationException(
                            sprintf('Class "%s" was not found and cannot be used as content.', $key)
                        );
                    }

                    $entityConfig['class'] = class_exists($key) ? $key : null;

                    $processedContents[$slug] = $entityConfig;

                    if (in_array($slug, $existingEntityNames)) {
                        throw new RuntimeException(
                            sprintf('Multiple contents are configured using same slug "%s"', $slug)
                        );
                    }

                    $existingEntityNames[] = $slug;
                    $processedSlugs[$key] = $slug;
                }

//                $rawConfig['contents'] = $processedContents;
//                $rawConfig['slugs'] = $processedSlugs;
                $configs[$i]['content']['contents'] = $processedContents;
                $configs[$i]['content']['slugs'] = $processedSlugs;
            }

        }

        return $configs;
    }
}
