<?php

namespace Database\Seeders;

use FluxCms\Core\Models\CmsContent;
use Illuminate\Database\Seeder;
use Illuminate\Support\Arr;

class CmsContentSeeder extends Seeder
{
    /**
     * Files to skip entirely (handled by dedicated seeders or irrelevant).
     *
     * @var array<string>
     */
    protected array $skipFiles = [
        'faqs',
        'sections',
        'search_index',
        'validation',
        'auth',
        'passwords',
        'pagination',
    ];

    /**
     * Keys to skip within specific groups (handled by dedicated models).
     *
     * @var array<string, array<string>>
     */
    protected array $skipKeys = [
        'components' => ['news_band', 'industries_band'],
    ];

    public function run(): void
    {
        $locales = ['de', 'en'];

        $deFiles = glob(lang_path('de/*.php'));
        if (! $deFiles) {
            return;
        }

        foreach ($deFiles as $filePath) {
            $group = pathinfo($filePath, PATHINFO_FILENAME);

            if (in_array($group, $this->skipFiles)) {
                continue;
            }

            $translations = [];
            foreach ($locales as $locale) {
                $localePath = lang_path("{$locale}/{$group}.php");
                if (file_exists($localePath)) {
                    $translations[$locale] = require $localePath;
                }
            }

            if (empty($translations)) {
                continue;
            }

            $deData = $translations['de'] ?? [];
            $enData = $translations['en'] ?? [];

            $flatDe = $this->flatten($deData);
            $flatEn = $this->flatten($enData);

            $allKeys = array_keys($flatDe);
            foreach (array_keys($flatEn) as $enKey) {
                if (! in_array($enKey, $allKeys)) {
                    $allKeys[] = $enKey;
                }
            }

            $order = 0;
            foreach ($allKeys as $key) {
                if ($this->shouldSkipKey($group, $key)) {
                    continue;
                }

                $deValue = $flatDe[$key] ?? null;
                $enValue = $flatEn[$key] ?? null;

                $type = $this->detectType($deValue ?? $enValue);

                $translatedValue = [];
                if ($deValue !== null) {
                    $translatedValue['de'] = is_string($deValue) ? $this->cleanHtml($deValue) : $deValue;
                }
                if ($enValue !== null) {
                    $translatedValue['en'] = is_string($enValue) ? $this->cleanHtml($enValue) : $enValue;
                }

                CmsContent::updateOrCreate(
                    ['group' => $group, 'key' => $key],
                    [
                        'type' => $type,
                        'value' => $translatedValue,
                        'order' => $order++,
                    ]
                );
            }
        }
    }

    /**
     * Flatten a nested array into dot-notation keys.
     * Arrays of objects (indexed arrays) are stored as JSON type.
     *
     * @return array<string, mixed>
     */
    protected function flatten(array $array, string $prefix = ''): array
    {
        $result = [];

        foreach ($array as $key => $value) {
            $fullKey = $prefix ? "{$prefix}.{$key}" : (string) $key;

            if (is_array($value) && ! Arr::isAssoc($value)) {
                $result[$fullKey] = $value;
            } elseif (is_array($value)) {
                $result = array_merge($result, $this->flatten($value, $fullKey));
            } else {
                $result[$fullKey] = $value;
            }
        }

        return $result;
    }

    protected function detectType(mixed $value): string
    {
        if (is_array($value)) {
            return 'json';
        }

        if (! is_string($value)) {
            return 'text';
        }

        if (preg_match('/<[a-z][\s\S]*>/i', $value)) {
            return 'html';
        }

        if (preg_match('/\.(jpg|jpeg|png|gif|webp|svg)(\?.*)?$/i', $value)) {
            return 'image';
        }

        if (preg_match('/\.(pdf|doc|docx)$/i', $value)) {
            return 'link';
        }

        return 'text';
    }

    /**
     * Clean HTML by converting font-weight spans to <strong> tags.
     * Preserves text-gradient-premium spans and email-protection spans.
     */
    protected function cleanHtml(string $value): string
    {
        $value = preg_replace(
            '/<span\s+class="[^"]*(?:font-semibold|font-bold)[^"]*">(\s*)(.*?)<\/span>/si',
            '$1<strong>$2</strong>',
            $value
        );

        return $value;
    }

    protected function shouldSkipKey(string $group, string $key): bool
    {
        if (! isset($this->skipKeys[$group])) {
            return false;
        }

        foreach ($this->skipKeys[$group] as $skipPrefix) {
            if ($key === $skipPrefix || str_starts_with($key, "{$skipPrefix}.")) {
                return true;
            }
        }

        return false;
    }
}
