# Plan: Omgjord flyerimport (pdf-parse + tesseract + Mistral Tiny)

## Mål
Ersätta nuvarande flyerimportflöde (som idag delegerar till `importer-api`) med en robust pipeline som:
1) extraherar text från flyer-PDF (primärt `pdf-parse`, fallback OCR via Tesseract),
2) skickar normaliserad text till Mistral Tiny,
3) returnerar strikt strukturerad JSON,
4) behåller befintlig matchning/planeringsflöde i backend + Flutter men förbättrar UX kring importresultat och fel.

## Nulägesanalys (projektanpassad)
- Backend endpoint finns: `POST /flyer-import/parse` i `backend/src/flyer-import/flyer-import.controller.ts`.
- Nuvarande backendlogik i `backend/src/flyer-import/flyer-import.service.ts` anropar extern tjänst via `IMPORTER_SERVICE_URL` (`/api/flyer/parse`).
- Flutter har redan komplett flyerflik i `flutter/lib/features/import/presentation/flyer_import_tab.dart`:
  - filval, importknapp, preview, radrendering med checkboxar, bulk-planering.
- Datamodell för sessions/items finns redan i Prisma (`FlyerSession`, `FlyerItem`, `FlyerSelection`) och stödjer parse+match-metadata.
- `flyerimporter.md` beskriver rätt riktning men är generisk; projektet behöver NestJS-integration och kompatibilitet med befintliga DTO/Flutter-modeller.

## Föreslagen arkitektur (ersättning av dagens lösning)

### 1) Ny intern parser i recipe-api (NestJS)
- Ersätt `parseViaImporter(...)` i `FlyerImportService` med lokal pipeline:
  - `extractFlyerText(file)`
    - PDF/text-extraktion via `pdf-parse`.
    - Fallback OCR via Tesseract för sidor/underlag utan användbar text.
  - `parseFlyerWithMistral(text)`
    - Mistral Tiny-anrop med strikt JSON-schema-prompt.
  - `normalizeFlyerItems(aiJson)`
    - validering, typkonvertering, enhetsnormalisering, confidence/reasonCodes.
- Behåll resten av tjänsten intakt (matchning, sessionpersistens, selections-kompatibilitet).

### 2) AI-kontrakt (strikt JSON)
- Introducera explicit schema för AI-svar (intern typ + runtime-validering):
  - `rawName`, `normalizedName`, `category`, `price`, `priceUnit`, `comparisonPrice`, `comparisonUnit`, `offerText`, `confidence`, `reasonCodes`.
- Promptdesign:
  - svensk flyer-kontext,
  - tydlig enhets- och prisnormalisering,
  - "returnera ENDAST JSON" + exempel,
  - fallback vid saknade fält (`null`, tomma listor).
- Robust parsing av modelloutput:
  - ta bort ev. markdown fences,
  - fail-fast med tydligt felmeddelande om ogiltigt JSON.

### 3) OCR-strategi
- Primärväg: `pdf-parse` (snabb, billig).
- OCR-fallback: bara när extraherad text är tom/under tröskel.
- Preprocess för OCR (vid behov): sidvis rasterisering + språk `swe` (ev. `swe+eng`).
- Timeout/guardrails per steg för att undvika låsta importer.

### 4) API/infra-anpassning
- Controller (`flyer-import.controller.ts`):
  - uppdatera tillåtna MIME-typer så de matchar Flutter-filtyper (PDF + bilder om vi ska stödja bildflyers).
- `compose.yml`/env:
  - gör `IMPORTER_SERVICE_URL` optional eller avveckla för flyerflödet.
  - säkerställ `MISTRAL_API_KEY` används av `recipe-api` för flyer.
- Dokumentation:
  - uppdatera teknisk beskrivning så flyerimport inte längre kräver extern flyer-parser.

## UX-analys Flutter (nuvarande) och planerade förbättringar

### Nuvarande UX (bra att bygga vidare på)
- Enkel 3-stegsinteraktion: välj fil -> importera -> markera/planera.
- Förhandsvisning finns och passar arbetsflödet.
- Offer-badge + pris/jämförpris + matchvisning ger snabb scanning.

### UX-gap att täppa till i denna implementation
- Ingen tydlig visning av parserwarnings från backend (fältet `warnings` finns i modellen).
- Ingen kvalitetssignal i UI trots att `parseConfidence/matchConfidence` finns.
- Felmeddelanden är relativt råa; saknar råd per feltyp (timeout, ogiltig fil, AI-svar oformaterat).

### Föreslagna UX-förbättringar (inkrementella, kompatibla)
1. Visa `warnings` över resultatlistan i en kompakt varningspanel.
2. Lägg till "kvalitetsindikator" per rad (t.ex. låg/medel/hög) baserat på `parseConfidence` + `matchConfidence`.
3. Lägg till filterchips: `Endast erbjudanden`, `Saknar matchning`, `Låg kvalitet`.
4. Förbättra loading-state med stegnära text ("Extraherar text", "Tolkar med AI", "Matchar produkter").
5. Felmappning till användarvänliga meddelanden i `showErrorDialog` (teknisk detalj i kopierbar sekundärtext).

## Implementationsplan (ordning)

### Fas A - Backend kärna
1. Lägg till dependencies i `backend/package.json` för PDF/OCR/Mistral-klient.
2. Skapa intern flyer-parser service i `backend/src/flyer-import/` (text extraction + AI parse).
3. Byt `parseViaImporter` till intern implementation i `FlyerImportService`.
4. Lägg till runtime-validering och normalisering av AI-svar.

### Fas B - Kontrakt och robusthet
5. Säkerställ att response-format fortsatt matchar `FlyerImportResponse` (ingen breaking change mot Flutter).
6. Förbättra controller MIME-regler så de stämmer med faktiska stödda format.
7. Lägg till tydliga felkoder/meddelanden för:
   - tom/oläsbar flyer,
   - AI-parsefel,
   - timeout/service unavailable.

### Fas C - Flutter UX på befintlig skärm
8. Visa backend `warnings` i `flyer_import_tab.dart`.
9. Lägg till kvalitetsindikator + minimala filterchips.
10. Förfina loading/feltexter utan att ändra grundlayouten.

### Fas D - Verifiering
11. Backendtester för intern flyer-parser (happy path + fallback + felbanor).
12. Uppdatera/addera Flutter widgettester för warnings/indikator/filter.
13. Manuell E2E: PDF med text, PDF med skannade sidor, bildflyer, trasig fil.

## Filer som sannolikt berörs vid implementation
- `backend/src/flyer-import/flyer-import.service.ts`
- `backend/src/flyer-import/flyer-import.controller.ts`
- `backend/src/flyer-import/dto/flyer-import.response.ts` (endast om extra metadata behövs)
- `backend/package.json`
- `flutter/lib/features/import/presentation/flyer_import_tab.dart`
- Ev. `flutter/lib/features/import/domain/flyer_import_item.dart` (om ny UI-metadata exponeras)
- Dokumentation: `TEKNISK_BESKRIVNING.md` (kort uppdatering av arkitektur)

## Risker och mitigering
- OCR-prestanda/latens: använd fallback-only och timeout.
- Mistral kan ge semistrukturerat svar: strikt schema + robust JSON-sanitizing + validering.
- Kostnad/kvot på AI-anrop: minimera promptstorlek, trunkera brus, återanvänd normalisering.
- Driftöverraskningar: behåll endpoint-kontrakt oförändrat mot Flutter.

## Acceptance criteria
- Flyerimport fungerar utan beroende av extern `/api/flyer/parse` i importer-api.
- Minst en PDF med inbäddad text och en skannad PDF importeras framgångsrikt.
- Backend returnerar valid `FlyerImportResponse` och befintlig planeringsfunktion fortsätter fungera.
- Flutter visar warnings och gör det tydligare vilka rader som behöver manuell granskning.

## Fastställt beslut
- Första leveransen ska stödja **PDF + bildfiler** (`png/jpg/webp`) fullt ut.
