<?php

namespace App\Services\Keywords;

use Illuminate\Support\Str;

class KeywordSeedBuilder
{
    /**
     * @param  list<array<string, mixed>>  $candidates
     * @return list<string>
     */
    public function build(
        string $brandName,
        string $category,
        string $subcategory,
        array $candidates,
    ): array {
        $seeds = [];
        $limit = max(1, (int) config('google-ads.max_seeds', 15));

        foreach ([
            trim($subcategory),
            trim($category),
            trim($brandName),
        ] as $seed) {
            $this->pushSeed($seeds, $seed);
        }

        foreach ($this->combinedSeeds($brandName, $category, $subcategory) as $seed) {
            $this->pushSeed($seeds, $seed);
        }

        foreach ($candidates as $candidate) {
            if (count($seeds) >= $limit) {
                break;
            }

            $name = trim((string) ($candidate['name'] ?? ''));

            if ($name === '') {
                continue;
            }

            $this->pushSeed($seeds, $this->shortProductSeed($name));

            if ($category !== '') {
                $this->pushSeed($seeds, trim("{$category} {$this->shortProductSeed($name)}"));
            }
        }

        return array_slice($seeds, 0, $limit);
    }

    /**
     * @param  array<string, mixed>  $candidate
     * @return list<string>
     */
    public function seedsForCandidate(
        string $brandName,
        string $category,
        string $subcategory,
        array $candidate,
    ): array {
        $seeds = [];
        $name = trim((string) ($candidate['name'] ?? ''));

        if ($name === '') {
            return [];
        }

        $shortName = $this->shortProductSeed($name);
        $this->pushSeed($seeds, $shortName);

        if ($category !== '') {
            $this->pushSeed($seeds, trim("{$category} {$shortName}"));
        }

        if ($subcategory !== '') {
            $this->pushSeed($seeds, trim("{$subcategory} {$shortName}"));
        }

        if ($brandName !== '' && $category !== '') {
            $this->pushSeed($seeds, trim("{$brandName} {$shortName}"));
        }

        return $seeds;
    }

    /**
     * @param  list<string>  $seeds
     */
    private function pushSeed(array &$seeds, string $seed): void
    {
        $normalized = $this->normalizeSeed($seed);

        if ($normalized === '' || in_array($normalized, $seeds, true)) {
            return;
        }

        $seeds[] = $normalized;
    }

    /**
     * @return list<string>
     */
    private function combinedSeeds(string $brandName, string $category, string $subcategory): array
    {
        $combined = [];

        if ($brandName !== '' && $category !== '') {
            $combined[] = "{$brandName} {$category}";
        }

        if ($brandName !== '' && $subcategory !== '') {
            $combined[] = "{$brandName} {$subcategory}";
        }

        if ($category !== '' && $subcategory !== '') {
            $combined[] = "{$category} {$subcategory}";
        }

        return $combined;
    }

    private function shortProductSeed(string $name): string
    {
        $words = preg_split('/\s+/', Str::lower($name)) ?: [];
        $words = array_values(array_filter($words, fn (string $word): bool => strlen($word) > 2));

        return implode(' ', array_slice($words, 0, 6));
    }

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