<?php

namespace App\Services\Keywords;

use Illuminate\Support\Str;

class ProductKeywordParser
{
    /**
     * @return array{primary: string, related: list<string>}
     */
    public function parse(mixed $keywords, mixed $legacyPrimary = null, mixed $legacyRelated = null): array
    {
        $primary = '';
        $related = [];

        if (is_array($keywords)) {
            $primary = trim((string) ($keywords['primary'] ?? ''));
            $related = $this->normalizeRelatedList($keywords['related'] ?? []);
        }

        if ($primary === '' && is_string($legacyPrimary)) {
            $primary = trim($legacyPrimary);
        }

        if ($related === [] && is_array($legacyRelated)) {
            $related = $this->normalizeRelatedList($legacyRelated);
        }

        return [
            'primary' => $this->normalizeSeed($primary),
            'related' => $related,
        ];
    }

    /**
     * @param  array<string, mixed>  $candidate
     * @return list<string>
     */
    public function seedsFromCandidate(array $candidate): array
    {
        $parsed = $this->parse(
            $candidate['product_keywords'] ?? $candidate['keywords'] ?? null,
            $candidate['keyword_primary'] ?? null,
            $candidate['keyword_related'] ?? null,
        );

        $seeds = [];

        if ($parsed['primary'] !== '') {
            $seeds[] = $parsed['primary'];
        }

        foreach ($parsed['related'] as $related) {
            $seeds[] = $related;
        }

        return array_values(array_unique($seeds));
    }

    /**
     * @param  list<array<string, mixed>>  $candidates
     * @return list<string>
     */
    public function seedsFromCandidates(array $candidates): array
    {
        $seeds = [];

        foreach ($candidates as $candidate) {
            if (! is_array($candidate)) {
                continue;
            }

            foreach ($this->seedsFromCandidate($candidate) as $seed) {
                if (! in_array($seed, $seeds, true)) {
                    $seeds[] = $seed;
                }
            }
        }

        return $seeds;
    }

    /**
     * @param  array<string, mixed>  $row
     * @return array{primary: string, related: list<string>}|null
     */
    public function productKeywordsFromRow(array $row): ?array
    {
        $parsed = $this->parse(
            $row['keywords'] ?? $row['product_keywords'] ?? null,
            $row['keyword_primary'] ?? null,
            $row['keyword_related'] ?? null,
        );

        if ($parsed['primary'] === '' && $parsed['related'] === []) {
            return null;
        }

        return $parsed;
    }

    /**
     * @return list<string>
     */
    private function normalizeRelatedList(mixed $related): array
    {
        if (! is_array($related)) {
            return [];
        }

        $normalized = [];

        foreach ($related as $value) {
            $seed = $this->normalizeSeed((string) $value);

            if ($seed === '' || in_array($seed, $normalized, true)) {
                continue;
            }

            $normalized[] = $seed;
        }

        return array_slice($normalized, 0, 5);
    }

    public function normalizeSeed(string $seed): string
    {
        return trim(preg_replace('/\s+/', ' ', Str::lower($seed)) ?? '');
    }
}
