<?php
/**
 * Cod produs sync — propagarea codului de produs (part_number / SKU intern) de
 * pe contul normal pe contul FBE.
 *
 * Același produs fizic există pe ambele conturi și ar trebui să aibă același
 * „cod produs" (emag_part_number). În practică, codul de pe FBE rămâne adesea în
 * urmă (ex: contul normal are un sufix `_V3` pe care FBE nu îl are). Această
 * pagină pune codurile față în față și permite împingerea codului normal → FBE.
 *
 * Potrivirea produselor între conturi e „elastică" (identică cu pagina de
 * Comparație): două produse sunt ACELAȘI produs dacă împart EAN-ul sau PNK-ul.
 */

require_once __DIR__ . '/db.php';

/** Normalizează o valoare de câmp: trim; '' și null → null. */
function _cps_norm($v): ?string
{
    if ($v === null) return null;
    $v = trim((string)$v);
    return $v === '' ? null : $v;
}

/**
 * Construiește planul „cod produs sync": perechile normal ↔ FBE cu codurile lor.
 *
 * @return array{
 *   normal: ?array{id:int, account_name:string},
 *   fbe: ?array{id:int, account_name:string},
 *   rows: array<int, array>,
 *   stats: array{total:int, same:int, diff:int, missing:int, syncable:int}
 * }
 */
function cps_build_plan(): array
{
    $accounts = db_select(
        "SELECT id, account_name, is_fbe FROM emag_accounts
         WHERE is_active = 1
         ORDER BY is_fbe ASC, account_name COLLATE NOCASE ASC"
    );

    $normal = null; $fbe = null;
    foreach ($accounts as $a) {
        if ((int)$a['is_fbe'] === 1) { if ($fbe === null) $fbe = $a; }
        else                         { if ($normal === null) $normal = $a; }
    }

    $out = [
        'normal' => $normal ? ['id' => (int)$normal['id'], 'account_name' => $normal['account_name']] : null,
        'fbe'    => $fbe    ? ['id' => (int)$fbe['id'],    'account_name' => $fbe['account_name']]    : null,
        'rows'   => [],
        'stats'  => ['total' => 0, 'same' => 0, 'diff' => 0, 'missing' => 0, 'syncable' => 0],
    ];

    if (!$normal || !$fbe) return $out;

    $normalId = (int)$normal['id'];
    $fbeId    = (int)$fbe['id'];

    $products = db_select(
        "SELECT id, emag_account_id, emag_id, ean, pnk, product_name, emag_part_number
         FROM products
         WHERE emag_account_id IN (?, ?)",
        [$normalId, $fbeId]
    );

    // ---- Union-find pe chei EAN / PNK (același algoritm ca la Comparație) ----
    $parent = [];
    $find = function (string $x) use (&$parent): string {
        while ($parent[$x] !== $x) {
            $parent[$x] = $parent[$parent[$x]];
            $x = $parent[$x];
        }
        return $x;
    };
    $union = function (string $a, string $b) use (&$parent, $find): void {
        $ra = $find($a); $rb = $find($b);
        if ($ra !== $rb) $parent[$ra] = $rb;
    };

    foreach ($products as &$p) {
        $p['ean']              = _cps_norm($p['ean']);
        $p['pnk']              = _cps_norm($p['pnk']);
        $p['product_name']     = _cps_norm($p['product_name']);
        $p['emag_part_number'] = _cps_norm($p['emag_part_number']);

        $keys = [];
        if ($p['ean'] !== null) $keys[] = 'e:' . $p['ean'];
        if ($p['pnk'] !== null) $keys[] = 'p:' . $p['pnk'];
        if (!$keys) $keys[] = 'id:' . $p['id'];

        foreach ($keys as $k) {
            if (!isset($parent[$k])) $parent[$k] = $k;
        }
        for ($i = 1, $n = count($keys); $i < $n; $i++) {
            $union($keys[0], $keys[$i]);
        }
        $p['_primary_key'] = $keys[0];
    }
    unset($p);

    // ---- Grupare pe componentă conectată ----
    $groups = [];
    foreach ($products as $p) {
        $root = $find($p['_primary_key']);
        $groups[$root][] = $p;
    }

    $rows = [];
    foreach ($groups as $members) {
        // Primul membru per cont (de regulă unul singur).
        $n = null; $f = null;
        foreach ($members as $m) {
            if ((int)$m['emag_account_id'] === $normalId && $n === null) $n = $m;
            if ((int)$m['emag_account_id'] === $fbeId    && $f === null) $f = $m;
        }

        $normalCode = $n['emag_part_number'] ?? null;
        $fbeCode    = $f['emag_part_number'] ?? null;

        // Etichetă (nume + PNK/EAN reprezentativ) din oricare membru disponibil.
        $name = ($n['product_name'] ?? null) ?? ($f['product_name'] ?? null);
        $pnk  = ($n['pnk'] ?? null) ?? ($f['pnk'] ?? null);
        $ean  = ($n['ean'] ?? null) ?? ($f['ean'] ?? null);

        // Status:
        //   missing_normal / missing_fbe → lipsește produsul pe un cont
        //   no_source → produsul FBE există dar contul normal n-are cod de trimis
        //   same → codurile coincid
        //   diff → codurile diferă (ținta principală de sync)
        if (!$n)                     $status = 'missing_normal';
        elseif (!$f)                 $status = 'missing_fbe';
        elseif ($normalCode === null)$status = 'no_source';
        elseif ($fbeCode === $normalCode) $status = 'same';
        else                         $status = 'diff';

        // Se poate sincroniza doar dacă: există produs FBE cu emag_id, contul
        // normal are un cod, iar codurile diferă.
        $fbeEmagId = _cps_norm($f['emag_id'] ?? null);
        $syncable  = ($status === 'diff') && ($fbeEmagId !== null);

        $rows[] = [
            'name'          => $name,
            'pnk'           => $pnk,
            'ean'           => $ean,
            'status'        => $status,
            'syncable'      => $syncable,
            'normal_id'     => $n ? (int)$n['id'] : null,
            'normal_code'   => $normalCode,
            'normal_pnk'    => $n['pnk'] ?? null,
            'fbe_id'        => $f ? (int)$f['id'] : null,
            'fbe_emag_id'   => $fbeEmagId,
            'fbe_code'      => $fbeCode,
            'fbe_pnk'       => $f['pnk'] ?? null,
        ];

        $out['stats']['total']++;
        if ($status === 'same')  $out['stats']['same']++;
        if ($status === 'diff')  $out['stats']['diff']++;
        if ($status === 'missing_normal' || $status === 'missing_fbe') $out['stats']['missing']++;
        if ($syncable)           $out['stats']['syncable']++;
    }

    // Sortare: întâi diferențele (sync-abile primele), apoi lipsă, apoi identice.
    $rank = ['diff' => 0, 'no_source' => 1, 'missing_fbe' => 2, 'missing_normal' => 3, 'same' => 4];
    usort($rows, function ($a, $b) use ($rank) {
        // sync-abile înaintea celor ne-sync-abile din același status
        $ra = $rank[$a['status']] ?? 9; $rb = $rank[$b['status']] ?? 9;
        if ($ra !== $rb) return $ra <=> $rb;
        if ($a['syncable'] !== $b['syncable']) return $a['syncable'] ? -1 : 1;
        return strcasecmp((string)$a['name'], (string)$b['name']);
    });

    $out['rows'] = $rows;
    return $out;
}
