<?php

namespace App\Services;

use App\Models\Brand;
use App\Models\TranslationDictionary;
use App\Models\TranslationCache;

/**
 * ProductTranslationService
 *
 * Brand-aware, dictionary-driven Arabic product name suggestion engine.
 * Translation workflow:
 * 1. Check translation cache for full phrase
 * 2. Tokenize and check brand master (never semantically translate brand names)
 * 3. Tokenize and check translation dictionary
 * 4. Normalize size/unit patterns (24 X 320 ML → 24 × 320 مل)
 * 5. Assemble and cache result
 */
class ProductTranslationService
{
    /** Arabic numeral mapping for unit normalization */
    private array $unitArabicMap = [
        'GM'   => 'جرام',
        'G'    => 'جرام',
        'KG'   => 'كجم',
        'ML'   => 'مل',
        'LTR'  => 'لتر',
        'L'    => 'لتر',
        'CTN'  => 'كرتون',
        'PCS'  => 'قطعة',
        'PCS.' => 'قطعة',
        'BOX'  => 'صندوق',
        'PKT'  => 'باكيت',
        'DOZ'  => 'درزن',
    ];

    public function suggest(string $englishName): string
    {
        if (empty(trim($englishName))) return '';

        $key = strtoupper(trim($englishName));

        // Step 1: Check translation cache
        $cached = TranslationCache::where('english_text', $key)->first();
        if ($cached) {
            return $cached->arabic_text;
        }

        // Step 2: Build brand lookup map
        $brands = Brand::where('status', 'active')
            ->get()
            ->mapWithKeys(fn($b) => [strtoupper($b->name_en) => $b->name_ar])
            ->toArray();

        // Step 3: Build dictionary lookup map
        $dict = TranslationDictionary::all()
            ->mapWithKeys(fn($d) => [strtoupper($d->english_term) => $d->arabic_term])
            ->toArray();

        // Merge: brand translations override dictionary to prevent semantic mistranslation
        $lookup = array_merge($dict, $brands);

        // Step 4: Tokenize and translate
        $tokens = preg_split('/(\s+)/', $key, -1, PREG_SPLIT_DELIM_CAPTURE);
        $arabicTokens = [];

        $i = 0;
        while ($i < count($tokens)) {
            $token = $tokens[$i];
            $trimmed = trim($token);

            if ($trimmed === '') {
                $arabicTokens[] = ' ';
                $i++;
                continue;
            }

            // Check if this is a size pattern: NUMBER X NUMBER UNIT (e.g., 24 X 320 ML)
            if (preg_match('/^(\d+)$/', $trimmed) && isset($tokens[$i+2]) && strtoupper(trim($tokens[$i+2])) === 'X') {
                // Try to capture: N X N UNIT
                $qty1 = $trimmed;
                $qty2 = isset($tokens[$i+4]) ? trim($tokens[$i+4]) : null;
                $unit = isset($tokens[$i+6]) ? strtoupper(trim($tokens[$i+6])) : null;

                if ($qty2 && preg_match('/^\d+$/', $qty2) && $unit && isset($this->unitArabicMap[$unit])) {
                    $arabicTokens[] = $qty1 . ' × ' . $qty2 . ' ' . $this->unitArabicMap[$unit];
                    $i += 7; // Skip N, space, X, space, N, space, UNIT
                    continue;
                }
            }

            // Normalize unit tokens
            if (isset($this->unitArabicMap[$trimmed])) {
                $arabicTokens[] = $this->unitArabicMap[$trimmed];
                $i++;
                continue;
            }

            // Check lookup table (brand then dictionary)
            if (isset($lookup[$trimmed])) {
                $arabicTokens[] = $lookup[$trimmed];
                $i++;
                continue;
            }

            // Try multi-word lookup (2 and 3 word combos)
            $found = false;
            foreach ([3, 2] as $wordCount) {
                $multiKey = '';
                for ($j = 0; $j < $wordCount && ($i + $j * 2) < count($tokens); $j++) {
                    $multiKey .= trim($tokens[$i + $j * 2]);
                    if ($j < $wordCount - 1) $multiKey .= ' ';
                }
                if (isset($lookup[$multiKey])) {
                    $arabicTokens[] = $lookup[$multiKey];
                    $i += $wordCount * 2 - 1;
                    $found = true;
                    break;
                }
            }

            if (!$found) {
                // Keep numeric tokens and special chars as-is
                if (preg_match('/^[\d\.\,\-\/\%\×x]+$/', $trimmed)) {
                    $arabicTokens[] = $trimmed;
                } else {
                    // Keep unknown English token (user must review)
                    $arabicTokens[] = $trimmed;
                }
                $i++;
            }
        }

        $arabic = implode(' ', array_filter($arabicTokens, fn($t) => $t !== ' '));
        // Clean up extra spaces
        $arabic = preg_replace('/\s+/', ' ', trim($arabic));

        // Step 5: Cache the result
        if (!empty($arabic) && $arabic !== $key) {
            TranslationCache::updateOrCreate(
                ['english_text' => $key],
                ['arabic_text'  => $arabic]
            );
        }

        return $arabic;
    }

    /**
     * Batch translate an array of English names.
     * Returns ['english' => 'arabic'] map.
     */
    public function batchSuggest(array $englishNames): array
    {
        $results = [];
        foreach ($englishNames as $name) {
            $results[$name] = $this->suggest($name);
        }
        return $results;
    }
}
