---
phase: 06-sonarqube-quality
plan: 04
type: execute
wave: 2
depends_on: []
files_modified:
  - src/Modules/Settings/AllegroIntegrationController.php
  - src/Modules/Settings/ShopproIntegrationsController.php
  - src/Modules/Settings/ShopproOrdersSyncService.php
autonomous: true
---

<objective>
## Goal
Obniżyć złożoność kognitywną (cognitive complexity) w 5 najbardziej skomplikowanych metodach — eliminacja naruszeń SonarQube php:S3776 (31 wystąpień).

## Purpose
Metody z zagnieżdżonymi if/foreach/switch na 4+ poziomach są trudne do testowania i modyfikacji. Wydzielenie fragmentów do private helper methods upraszcza główny przepływ i obniża wynik SonarQube poniżej progu 15.

## Output
Zmniejszona złożoność w 5 kluczowych metodach w 3 plikach. SonarQube S3776 spada z 31 do ~15.
</objective>

<context>
## Project Context
@.paul/PROJECT.md

## Source Files
@src/Modules/Settings/AllegroIntegrationController.php
@src/Modules/Settings/ShopproIntegrationsController.php
@src/Modules/Settings/ShopproOrdersSyncService.php
</context>

<skills>
## Required Skills (from SPECIAL-FLOWS.md)

| Skill | Priority | When to Invoke | Loaded? |
|-------|----------|----------------|---------|
| sonar-scanner | required | Po APPLY, przed UNIFY | ○ |

## Skill Invocation Checklist
- [ ] sonar-scanner uruchomiony po zakończeniu APPLY
</skills>

<acceptance_criteria>

## AC-1: AllegroIntegrationController::oauthCallback() uproszczone
```gherkin
Given oauthCallback() ma 6 zagnieżdżonych if (validation chain)
When wydzielasz każdy blok walidacji do osobnej private metody
Then oauthCallback() ma max 2 poziomy zagnieżdżenia
```

## AC-2: AllegroIntegrationController::loadDeliveryServices() uproszczone
```gherkin
Given loadDeliveryServices() ma try-catch z 4 poziomami zagnieżdżenia
When wydzielasz ładowanie Allegro services i Apaczka services do osobnych private metod
Then loadDeliveryServices() ma max 2 poziomy zagnieżdżenia
```

## AC-3: ShopproIntegrationsController::saveStatusMappings() uproszczone
```gherkin
Given saveStatusMappings() ma 3 zagnieżdżone pętle (foreach w foreach z if)
When wydzielasz przetwarzanie pojedynczego mappingu do private metody
Then saveStatusMappings() ma max 2 poziomy zagnieżdżenia
```

## AC-4: ShopproOrdersSyncService::sync() uproszczone
```gherkin
Given sync() (195 linii) ma triple nested loop (for pages > foreach candidates > try-catch > if)
When wydzielasz przetwarzanie pojedynczej strony do private processPage() i pojedynczego zamówienia do processCandidate()
Then sync() ma max 3 poziomy zagnieżdżenia; główna pętla jest czytelna
```

## AC-5: Brak regresji
```gherkin
Given funkcjonalność działa przed refaktoryzacją
When zmiany są czysto strukturalne (extract method, nie zmiana logiki)
Then zachowanie identyczne — OAuth flow, status mappings, sync działają
```

</acceptance_criteria>

<tasks>

<task type="auto">
  <name>Task 1: Uproszczenie AllegroIntegrationController — oauthCallback() i loadDeliveryServices()</name>
  <files>src/Modules/Settings/AllegroIntegrationController.php</files>
  <action>
    Przeczytaj oauthCallback() i loadDeliveryServices() dokładnie.

    **oauthCallback() — wzorzec uproszczenia:**
    Każdy blok `if (warunek) { flash error; return; }` to kandydat do wydzielenia.
    Stwórz private validateOAuthState(array $params): bool — sprawdza state parameter
    Stwórz private validateOAuthCode(array $params): bool — sprawdza code parameter
    Główna metoda: series of guard checks bez zagnieżdżenia.
    Docelowy kształt:
    ```php
    public function oauthCallback(): void {
        if (!$this->validateOAuthState($params)) { [flash + redirect]; return; }
        if (!$this->validateOAuthCode($params)) { [flash + redirect]; return; }
        // logika bez zagnieżdżenia
    }
    ```

    **loadDeliveryServices() — wzorzec uproszczenia:**
    Wydziel ładowanie Allegro delivery services do private loadAllegroDeliveryServices(): array
    Wydziel ładowanie Apaczka services do private loadApaczkaServices(): array
    Główna metoda wywołuje oba i buduje odpowiedź — bez zagnieżdżonych try-catch.
    Każda z wydzielonych metod ma swój własny try-catch wewnętrznie.

    Zasady:
    - NIE zmieniaj logiki — tylko gdzie jest kod
    - NIE zmieniaj komunikatów, flash keys, redirect paths
    - Nowe private metody na końcu klasy
  </action>
  <verify>
    php -l src/Modules/Settings/AllegroIntegrationController.php
    Ręczne sprawdzenie oauthCallback(): max 2 poziomy zagnieżdżenia w ciele metody
    Ręczne sprawdzenie loadDeliveryServices(): max 2 poziomy zagnieżdżenia
  </verify>
  <done>AC-1, AC-2 satisfied: obie metody uproszczone, składnia poprawna</done>
</task>

<task type="auto">
  <name>Task 2: Uproszczenie ShopproIntegrationsController — saveStatusMappings()</name>
  <files>src/Modules/Settings/ShopproIntegrationsController.php</files>
  <action>
    Przeczytaj saveStatusMappings() i loadDeliveryServices().

    **saveStatusMappings() — wzorzec uproszczenia:**
    Jeśli metoda zawiera zagnieżdżone foreach z logiką wewnątrz:
    ```php
    foreach ($mappings as $mapping) {
        foreach ($mapping['items'] as $item) {
            if (...) {
                // logika
            }
        }
    }
    ```
    Wydziel wewnętrzny foreach+if do private processMappingItem(array $item, ...): void
    lub private processSingleStatusMapping(array $mapping): void

    **loadDeliveryServices() (jeśli jest w Shoppro):**
    Ten sam wzorzec co Allegro — wydziel ładowanie per-provider.

    Główna zasada: metoda po refaktoryzacji powinna być "czytalna jak lista kroków" — bez zagłębiania się w szczegóły.

    NIE zmieniaj logiki biznesowej.
    Nowe private metody na końcu klasy.
  </action>
  <verify>
    php -l src/Modules/Settings/ShopproIntegrationsController.php
    Ręczne sprawdzenie saveStatusMappings(): max 2 poziomy zagnieżdżenia
  </verify>
  <done>AC-3 satisfied: saveStatusMappings() uproszczone</done>
</task>

<task type="auto">
  <name>Task 3: Uproszczenie ShopproOrdersSyncService::sync()</name>
  <files>src/Modules/Settings/ShopproOrdersSyncService.php</files>
  <action>
    Przeczytaj metodę sync() (ok. 195 linii).

    **sync() — wzorzec uproszczenia:**
    Obecna struktura (schemat):
    ```
    foreach ($integrations) {
        for ($page = 1; ...) {
            foreach ($candidates) {
                try {
                    if (...) {
                        // przetwarzanie zamówienia
                    }
                } catch (...) { ... }
            }
        }
    }
    ```

    Wydziel:
    1. private processOrderCandidate(array $candidate, array $integration, array $statusMap, ...): void
       - zawiera: try-catch + logikę przetwarzania jednego zamówienia
    2. private processPageCandidates(array $candidates, array $integration, array $statusMap, array &$results): void
       - zawiera: foreach ($candidates) + wywołanie processOrderCandidate()

    Po wydzieleniu sync() powinna wyglądać jak:
    ```
    foreach ($integrations) {
        for ($page = 1; ...) {
            $candidates = $this->buildCandidates($orders);
            $this->processPageCandidates($candidates, $integration, $statusMap, $results);
            if (brak kolejnej strony) break;
        }
    }
    ```

    Zachowaj wszystkie parametry które są potrzebne (przekaż przez argumenty lub &$results).
    NIE zmieniaj logiki przetwarzania — tylko gdzie jest kod.
  </action>
  <verify>
    php -l src/Modules/Settings/ShopproOrdersSyncService.php
    Ręczne sprawdzenie sync(): max 3 poziomy zagnieżdżenia (foreach integrations > for pages > processPageCandidates)
  </verify>
  <done>AC-4, AC-5 satisfied: sync() uproszczone, ShopproOrdersSyncService poprawna składniowo</done>
</task>

</tasks>

<boundaries>

## DO NOT CHANGE
- Logika biznesowa — warunkowa, obliczeniowa, API calls
- Komunikaty błędów, flash keys, redirect paths
- Publiczne sygnatury metod (public function names + parameters)
- Inne metody poza wymienionymi w AC
- Pliki poza files_modified

## SCOPE LIMITS
- Wydzielanie metod tylko wewnątrz istniejącej klasy (nie tworzyć nowych klas — to zakres 06-05)
- Nowe metody: private, na końcu klasy, jasna nazwa opisująca co robią
- Nie optymalizuj algorytmicznie — tylko strukturalnie

</boundaries>

<verification>
Przed zamknięciem planu:
- [ ] php -l na wszystkich 3 plikach — zero błędów
- [ ] oauthCallback() — max 2 poziomy zagnieżdżenia (ręczne sprawdzenie)
- [ ] loadDeliveryServices() (Allegro) — max 2 poziomy zagnieżdżenia
- [ ] saveStatusMappings() (Shoppro) — max 2 poziomy zagnieżdżenia
- [ ] sync() (ShopproOrdersSyncService) — max 3 poziomy zagnieżdżenia
- [ ] sonar-scanner — S3776 violations zmalały
</verification>

<success_criteria>
- Wszystkie 3 pliki bez błędów składniowych
- 5 wskazanych metod z zredukowanym zagnieżdżeniem
- SonarQube S3776 spada z 31 do ≤18
</success_criteria>

<output>
Po zakończeniu utwórz `.paul/phases/06-sonarqube-quality/06-04-SUMMARY.md`
</output>
