I have an existing Laravel project using Filament.

I want you to implement a production-ready feature for **matching product titles from a price-list PDF with products in the database**, reviewing the matches, and updating product names and prices.

## IMPORTANT: Existing Specification Files

I have already placed two reference files inside the project:

```text
specs/update-product-name/products.sql
specs/update-product-name/prices.pdf
```

These files are part of this feature specification and should be inspected before implementation.

### `products.sql`

This file contains the database/product data and should be used to understand the existing products and their names.

### `prices.pdf`

This file contains the actual price list and product titles that need to be matched against the products from `products.sql`.

**Use these two files as real-world test/reference data for this feature.**

Do not invent fake product data when the information can be obtained from these files.

Before implementation, inspect both files carefully and understand:

* Product names
* Product variations
* Weight/quantity information
* Packaging information
* Differences in Persian/Arabic characters
* Naming differences between the price list and database

---

# VERY IMPORTANT UI REQUIREMENT

I do NOT want a separate Product Matching Resource or a separate page in the admin panel.

The feature must be integrated directly into the existing:

```text
Products → Overview / List
```

page in Filament.

There should be a button/action on the existing Products list page.

For example:

```text
Products

[ Import / Match Price List ]
```

When the admin clicks this button:

**Open a Filament Modal.**

All price-list import, matching, review, and update functionality should happen through this modal/workflow.

Do not create an unnecessary standalone Product Matching page.

---

# 1. First Inspect the Existing Project

Before writing code:

1. Inspect the Laravel version.
2. Inspect the Filament version.
3. Find the existing Product Filament Resource.
4. Find the existing Products Overview/List page.
5. Inspect the existing Product model.
6. Inspect the `products` table migration/schema.
7. Inspect existing Services/Actions/Repositories.
8. Inspect existing file import functionality.
9. Inspect existing PDF parsing functionality if any.
10. Inspect existing authorization/policies.
11. Inspect existing activity/audit logging.
12. Inspect existing UI conventions.

Follow the existing architecture.

Do not unnecessarily introduce a new architecture if the project already has a suitable pattern.

Before modifying code, provide a short implementation plan.

---

# 2. Price List Source

The initial reference price list is:

```text
specs/update-product-name/prices.pdf
```

The database reference is:

```text
specs/update-product-name/products.sql
```

The implementation should be designed so that the admin can later upload a new price-list file, but these files must be used during development and testing.

The initial UI should support the price-list PDF workflow.

If the existing project already has a PDF parsing solution, reuse it.

If not, choose a lightweight and reliable solution appropriate for the existing Laravel project.

Do not add unnecessary dependencies.

---

# 3. Price List Data Extraction

Extract product information from the price-list PDF.

At minimum we need:

```text
Product title
Price
```

If the PDF contains additional useful information, preserve it when appropriate.

The extracted rows should be stored in a staging structure.

Suggested model:

```text
PriceListItem
```

Suggested table:

```text
price_list_items
```

Possible fields:

```text
id
import_id nullable
original_name
normalized_name
price nullable
matched_product_id nullable
match_score nullable
match_status
matched_name nullable
reviewed_at nullable
reviewed_by nullable
created_at
updated_at
```

If an import/session model makes sense:

```text
PriceListImport
```

with fields such as:

```text
id
file_name
status
created_by
created_at
updated_at
```

and:

```text
price_list_items.import_id
```

Use the existing project's architecture if there is already an import system.

---

# 4. Product Matching

Create a dedicated matching service.

For example:

```text
ProductMatcher
```

The matcher must compare:

```text
prices.pdf product title
```

against:

```text
products.name
```

and return the best candidates.

Example:

Price list:

```text
لوکوم زعفرانی بدون مغز سطلی 400 گرم
```

Database:

```text
لوكوم زعفرانی بدون مغز سطلی 400 گرمی
```

These should be considered a very strong match.

---

# 5. Persian Text Normalization

Create a reusable text normalization service.

For example:

```text
TextNormalizer
```

It should handle common differences such as:

```text
ي → ی
ى → ی
ك → ک
```

Also normalize:

* Persian/Arabic digits
* English digits
* Extra spaces
* Leading/trailing spaces
* Zero-width characters
* Half-spaces / نیم‌فاصله where appropriate
* Common punctuation
* Case differences
* Common weight/unit representations

Examples:

```text
400 گرم
400 گرمی
400g
```

should be recognized as closely related.

However, DO NOT remove important product attributes.

For example:

```text
مغزدار
بدون مغز
```

must remain different.

Likewise:

```text
400 گرم
900 گرم
```

must remain different.

---

# 6. Matching Algorithm

Do NOT use AI for the initial implementation.

Use a deterministic/rule-based matching engine.

Use a combination of appropriate techniques such as:

* Normalized exact match
* Token similarity
* Levenshtein distance
* `similar_text`
* Jaro-Winkler if useful
* Token-based similarity
* Important attribute comparison

Do not rely only on `similar_text()`.

The algorithm must identify meaningful conflicts.

For example:

```text
لوکوم زعفرانی بدون مغز 400 گرم
```

vs:

```text
لوکوم زعفرانی مغزدار 400 گرم
```

must NOT be treated as a confirmed match.

Likewise:

```text
نوقا پسته 700 گرم
```

vs:

```text
نوقا گردویی 700 گرم
```

must not be considered a confirmed match.

Likewise:

```text
400 گرم
```

vs:

```text
900 گرم
```

must not be considered a confirmed match.

Important attributes include:

* Product type
* Flavor
* Weight
* Quantity
* Packaging
* Nuts
* Filling
* Filled/non-filled
* Number of pieces
* Other meaningful descriptors

---

# 7. Matching Scores

Use configurable thresholds.

For example:

```text
confirmed >= 90
needs_review >= 70
not_found < 70
```

Create:

```text
config/product_matching.php
```

Example:

```php
return [
    'confirmed_threshold' => 90,
    'review_threshold' => 70,
    'candidate_limit' => 3,
];
```

Do not hard-code thresholds throughout the application.

---

# 8. Top Candidates

For every price-list item, find at least 3 candidates.

Example:

```text
Price List:
لوکوم زعفرانی بدون مغز 400 گرم

Candidates:

1. لوكوم زعفرانی بدون مغز سطلی 400 گرمی — 94%
2. لوكوم زعفرانی بدون مغز 900 گرمی — 78%
3. لوكوم زعفرانی مغزدار 400 گرمی — 71%
```

The admin must be able to choose the correct product manually.

---

# 9. Filament Modal Workflow

The entire workflow must happen from the existing Products List/Overview page.

Add a header action or suitable Filament action such as:

```text
Match Price List
```

or:

```text
Update Product Names
```

When clicked:

```text
OPEN MODAL
```

The modal should contain the workflow.

---

# 10. Modal Step 1 — Upload Price List

First step:

```text
Upload Price List
```

Allow the admin to upload the PDF price list.

Validate:

* File type
* File size
* Upload errors

After upload:

```text
Extract PDF
↓
Create Price List Items
↓
Run Matching
```

For the initial implementation, use:

```text
specs/update-product-name/prices.pdf
```

as the real reference file for testing.

---

# 11. Modal Step 2 — Matching Results

After processing, show matching results inside the modal.

Example:

| Price List Title      | Matched Product   | Score | Status       |
| --------------------- | ----------------- | ----: | ------------ |
| لوکوم زعفرانی 400 گرم | لوكوم زعفرانی ... |   96% | Confirmed    |
| نوقا پسته 700 گرم     | نوقا کادویی پسته  |   84% | Needs Review |
| ریس کاراملی           | —                 |   32% | Not Found    |

Use Filament badges/colors appropriately.

Statuses:

```text
Confirmed
Needs Review
Not Found
```

---

# 12. Modal Step 3 — Review

The admin should be able to review ambiguous matches directly inside the modal.

For each item show:

```text
Price List Title

Top Candidates:

1. Product A — 94%
2. Product B — 82%
3. Product C — 75%
```

Actions:

```text
Select
Reject
Search Product
Ignore
```

If necessary, allow the admin to search the existing `products` table manually.

---

# 13. Preview Changes Before Updating

This is very important.

Before changing the actual products, show a preview.

Example:

```text
Product #291

Current Name:
لوكوم زعفرانی بدون مغز سطلی 400 گرمی

New Name:
لوکوم زعفرانی بدون مغز سطلی 400 گرم

Current Price:
150000

New Price:
160000
```

The admin should explicitly confirm the update.

Do NOT modify products immediately after matching.

---

# 14. Update Options

Provide options such as:

```text
Update Name
Update Price
Update Name + Price
```

The admin must choose what should be synchronized.

For name:

```php
$product->update([
    'name' => $priceListItem->original_name,
]);
```

For price:

Use the appropriate existing price field from the Product model.

Do not assume the price column if the existing project has a different structure. Inspect the model/database first.

---

# 15. Bulk Approval

Inside the modal, allow selecting multiple confirmed/reviewed matches.

Actions:

```text
Approve Selected
```

and:

```text
Update Selected
```

Potentially:

```text
Update Names
Update Prices
Update Names + Prices
```

Do not allow unresolved `not_found` items to be updated accidentally.

---

# 16. Final Confirmation

Before performing bulk updates, show a confirmation dialog:

```text
You are about to update:

25 product names
18 product prices

Continue?
```

Then perform the update.

---

# 17. Database Transactions

All product updates must be wrapped in a database transaction.

If something fails:

```text
ROLLBACK
```

No partial update should be left behind.

---

# 18. Audit Logging

If the project already has an activity/audit log system, use it.

We should ideally be able to determine:

```text
Product ID
Old name
New name
Old price
New price
Who approved it
When it was updated
Which price-list import caused the change
```

Do not create a duplicate audit system if the project already has one.

---

# 19. Performance

The products table may eventually contain thousands or tens of thousands of records.

Do not compare every price-list item against every product with an expensive PHP loop if it can be avoided.

Use:

```text
Normalization
↓
Candidate Generation
↓
Similarity Calculation
↓
Top Candidates
```

Use database filtering to reduce candidates before expensive similarity calculations.

Avoid N+1 queries.

For large files, use Laravel Jobs/Queues if appropriate.

However, the modal should provide useful processing feedback rather than appearing frozen.

---

# 20. Architecture

Use clean separation of responsibilities.

Possible structure:

```text
app/
    Services/
        ProductMatching/
            TextNormalizer.php
            ProductMatcher.php
            SimilarityCalculator.php
            MatchResult.php
```

And:

```text
app/
    Models/
        PriceListImport.php
        PriceListItem.php
```

But follow the existing project's architecture if it already has equivalent patterns.

The Filament Product Resource/List page should only coordinate the UI/action.

Do not put the complete matching algorithm inside the Filament Resource.

---

# 21. Future AI Support

Do NOT use AI in this version.

However, design the matcher so AI can be added later.

For example:

```php
interface ProductMatchingStrategy
{
    public function match(
        string $title,
        Collection $products
    ): MatchResult;
}
```

Then later:

```text
RuleBasedProductMatcher
AiProductMatcher
```

The current implementation should use only:

```text
RuleBasedProductMatcher
```

AI may later be used only for ambiguous cases.

---

# 22. Tests Using the Real Files

Use the actual files:

```text
specs/update-product-name/products.sql
specs/update-product-name/prices.pdf
```

to validate the implementation.

Do not rely only on artificial test data.

Also create automated tests for:

### Persian character differences

```text
ي vs ی
ك vs ک
```

### Weight differences

```text
400 گرم vs 400 گرمی
```

### Different weights

```text
400 گرم vs 900 گرم
```

must not be a confirmed match.

### Filled vs non-filled

```text
مغزدار vs بدون مغز
```

must not be a confirmed match.

### Different nuts

```text
پسته vs گردو
```

must not be a confirmed match.

### Persian/English numbers

```text
۴۰۰ vs 400
```

### Spaces and half-spaces

```text
بدون مغز
بدون‌مغز
```

---

# 23. Important Safety Rule

The system must prioritize **correctness over aggressive matching**.

A false positive is more dangerous than a false negative.

If the system is uncertain:

```text
Needs Review
```

is preferable to:

```text
Confirmed
```

Never automatically rename a product because it has a moderately similar title.

---

# 24. User Experience

The desired flow is:

```text
Filament Products List
        ↓
[ Match / Update Product Names ]
        ↓
      Modal
        ↓
Upload prices.pdf
        ↓
Extract products
        ↓
Match against products
        ↓
Show results
        ↓
Review ambiguous matches
        ↓
Preview changes
        ↓
Admin confirmation
        ↓
Database transaction
        ↓
Update products
        ↓
Show success summary
```

The user should never need to leave the Products Overview page.

---

# 25. Success Summary

After the update, show something like:

```text
Import completed successfully.

Total price-list items: 121
Confirmed matches: 96
Manually reviewed: 15
Not found: 10

Names updated: 96
Prices updated: 96
```

The numbers must be generated dynamically.

---

# 26. Development Rules

Before finishing:

* Run migrations.
* Run tests.
* Run static analysis if available.
* Run Laravel Pint or the project's formatter.
* Check N+1 queries.
* Check authorization.
* Check validation.
* Check database transactions.
* Check error handling.
* Check modal UX.
* Check that existing Product List functionality still works.
* Do not modify unrelated features.

---

# 27. Final Report

When implementation is complete, report:

1. Files created.
2. Files modified.
3. Existing Product Resource/List page that was modified.
4. Matching architecture.
5. Matching algorithm.
6. PDF extraction approach.
7. Filament modal workflow.
8. How the admin reviews matches.
9. How names/prices are updated.
10. Tests added.
11. Commands executed.
12. Results from testing against:

    * `specs/update-product-name/products.sql`
    * `specs/update-product-name/prices.pdf`
13. Any assumptions.
14. Any limitations.
15. Any parts that could not be implemented.

Again:

**Do not create a standalone Product Matching page.**

The feature must be accessible directly from the existing Filament **Products Overview/List page through a button that opens a modal.**

The matching engine and business logic should remain outside the Filament UI layer so that it can be reused later.
