<?php

namespace App\Support;

use Illuminate\Support\Str;

class NavigationLinks
{
    /**
     * @param  array<int, array{label: string, href: string, icon?: string}>  $fallback
     * @return array<int, array{label: string, href: string, icon: string, external: bool}>
     */
    public static function parse(mixed $value, array $fallback = []): array
    {
        if (is_array($value)) {
            $lines = $value;
        } else {
            $lines = preg_split('/\r\n|\r|\n/', trim((string) $value)) ?: [];
        }

        $links = collect($lines)
            ->map(fn (mixed $line): ?array => self::parseLine($line))
            ->filter()
            ->values()
            ->all();

        if ($links !== []) {
            return $links;
        }

        return collect($fallback)
            ->map(fn (array $link): array => [
                'label' => (string) $link['label'],
                'href' => (string) $link['href'],
                'icon' => (string) ($link['icon'] ?? self::iconFor((string) $link['label'])),
                'external' => self::isExternal((string) $link['href']),
            ])
            ->values()
            ->all();
    }

    /**
     * @return array{label: string, href: string, icon: string, external: bool}|null
     */
    private static function parseLine(mixed $line): ?array
    {
        if (is_array($line)) {
            $label = trim((string) ($line['label'] ?? ''));
            $href = trim((string) ($line['href'] ?? $line['url'] ?? ''));
            $icon = trim((string) ($line['icon'] ?? ''));
        } else {
            $line = trim((string) $line);

            if ($line === '' || Str::startsWith($line, '#')) {
                return null;
            }

            [$label, $href, $icon] = array_pad(array_map('trim', explode('|', $line, 3)), 3, '');
        }

        if ($label === '' || ! self::isAllowedHref($href)) {
            return null;
        }

        return [
            'label' => $label,
            'href' => $href,
            'icon' => $icon !== '' ? $icon : self::iconFor($label),
            'external' => self::isExternal($href),
        ];
    }

    private static function isAllowedHref(string $href): bool
    {
        if ($href === '') {
            return false;
        }

        return Str::startsWith($href, ['#', '/', 'http://', 'https://', 'mailto:', 'tel:']);
    }

    private static function isExternal(string $href): bool
    {
        return Str::startsWith($href, ['http://', 'https://']);
    }

    private static function iconFor(string $label): string
    {
        $key = Str::of($label)->lower()->replace([' ', '_'], '-')->toString();

        return match (true) {
            Str::contains($key, 'linkedin') => 'linkedin',
            in_array($key, ['x', 'twitter'], true) || Str::contains($key, 'twitter') => 'x',
            Str::contains($key, 'facebook') => 'facebook',
            Str::contains($key, 'instagram') => 'instagram',
            Str::contains($key, 'youtube') => 'youtube',
            Str::contains($key, 'github') => 'github',
            Str::contains($key, ['mail', 'email', 'contact']) => 'mail',
            default => 'globe',
        };
    }
}
