<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Product;

class UpdateProductImagesSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $imageDir = public_path('images');

        if (!is_dir($imageDir)) {
            $this->command->info("Directory not found: {$imageDir}");
            return;
        }

        $files = array_values(array_filter(scandir($imageDir), function ($f) use ($imageDir) {
            return is_file($imageDir . DIRECTORY_SEPARATOR . $f);
        }));

        foreach (Product::all() as $product) {
            $matchedFile = $this->findMatch($product->name, $files);

            if ($matchedFile) {
                $product->image_url = '/images/' . $matchedFile;
                $product->save();
                $this->command->info("Updated image for: {$product->name} -> {$matchedFile}");
            } else {
                $this->command->info("No image found for: {$product->name}");
            }
        }
    }

    private function findMatch(string $productName, array $files): ?string
    {
        $pNorm = $this->normalize($productName);

        // exact match first
        foreach ($files as $file) {
            $nameOnly = pathinfo($file, PATHINFO_FILENAME);
            if ($this->normalize($nameOnly) === $pNorm) {
                return $file;
            }
        }

        // partial match (file contains product or product contains file)
        $best = null;
        $bestScore = 0;
        foreach ($files as $file) {
            $nameOnly = pathinfo($file, PATHINFO_FILENAME);
            $fNorm = $this->normalize($nameOnly);

            if (strpos($fNorm, $pNorm) !== false || strpos($pNorm, $fNorm) !== false) {
                $score = min(strlen($fNorm), strlen($pNorm));
                if ($score > $bestScore) {
                    $bestScore = $score;
                    $best = $file;
                }
            }
        }

        if ($best) {
            return $best;
        }

        // fallback: match by shared words
        $pWords = preg_split('/\s+/', $this->normalizeWords($productName));
        foreach ($files as $file) {
            $nameOnly = pathinfo($file, PATHINFO_FILENAME);
            $fWords = preg_split('/\s+/', $this->normalizeWords($nameOnly));
            $common = array_intersect($pWords, $fWords);
            if (count($common) >= 1) {
                return $file;
            }
        }

        // final fallback: check if filename (concatenated) contains any keyword from product name
        $best = null;
        $bestCount = 0;
        $pKeywords = preg_split('/\s+/', $this->normalizeWords($productName));
        foreach ($files as $file) {
            $nameOnly = pathinfo($file, PATHINFO_FILENAME);
            $fNorm = $this->normalize($nameOnly);
            $count = 0;
            foreach ($pKeywords as $kw) {
                $kw = trim($kw);
                if ($kw === '') continue;
                if (strpos($fNorm, $kw) !== false) {
                    $count++;
                }
            }
            if ($count > $bestCount) {
                $bestCount = $count;
                $best = $file;
            }
        }

        if ($bestCount > 0) {
            return $best;
        }

        return null;
    }

    private function normalize(string $s): string
    {
        $s = mb_strtolower($s);
        $s = preg_replace('/[^a-z0-9]+/', '', $s);
        return trim($s);
    }

    private function normalizeWords(string $s): string
    {
        $s = mb_strtolower($s);
        $s = preg_replace('/[^a-z0-9 ]+/', ' ', $s);
        $s = preg_replace('/\s+/', ' ', trim($s));
        return $s;
    }
}
