<?php
declare(strict_types=1);

/**
 * GS1 API diagnostic
 *
 * Usage:
 *   php bin/test_gs1_api.php <login> <password> [gtin]
 *
 * If login/password are not provided, script tries to read them from DB app_settings.
 */

$login = $argv[1] ?? '';
$password = $argv[2] ?? '';
$targetGtin = $argv[3] ?? '5905323904514';

if ($login === '' || $password === '') {
    $envFile = dirname(__DIR__) . '/.env';
    $env = [];
    if (is_file($envFile)) {
        foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
            $line = trim($line);
            if ($line === '' || $line[0] === '#') {
                continue;
            }
            $pos = strpos($line, '=');
            if ($pos === false) {
                continue;
            }
            $env[trim(substr($line, 0, $pos))] = trim(trim(substr($line, $pos + 1)), "\"'");
        }
    }

    try {
        $pdo = new PDO(
            sprintf(
                'mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4',
                $env['DB_HOST'] ?? '127.0.0.1',
                $env['DB_PORT'] ?? '3306',
                $env['DB_DATABASE'] ?? 'orderpro'
            ),
            $env['DB_USERNAME'] ?? 'root',
            $env['DB_PASSWORD'] ?? '',
            [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
        );

        $stmt = $pdo->prepare('SELECT setting_key, setting_value FROM app_settings WHERE setting_key IN (?, ?)');
        $stmt->execute(['gs1_api_login', 'gs1_api_password']);
        foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
            if ($row['setting_key'] === 'gs1_api_login') {
                $login = (string) $row['setting_value'];
            }
            if ($row['setting_key'] === 'gs1_api_password') {
                $password = (string) $row['setting_value'];
            }
        }
    } catch (Throwable) {
        // Ignore and use CLI args fallback.
    }
}

if ($login === '' || $password === '') {
    fwrite(STDERR, "Brak credentials. Uzyj: php bin/test_gs1_api.php <login> <password> [gtin]\n");
    exit(1);
}

if (!preg_match('/^\d{13,14}$/', $targetGtin)) {
    fwrite(STDERR, "Nieprawidlowy GTIN: {$targetGtin}. Oczekiwane 13 lub 14 cyfr.\n");
    exit(1);
}

const GS1_BASE = 'https://mojegs1.pl/api/v2';

/**
 * @return array{status:int, body:string, error:string}
 */
function gs1Request(
    string $method,
    string $url,
    string $login,
    string $password,
    ?string $rawBody = null,
    string $contentType = 'application/json',
    string $accept = 'application/json'
): array {
    $curl = curl_init($url);
    if ($curl === false) {
        return ['status' => 0, 'body' => '', 'error' => 'Nie mozna zainicjalizowac cURL'];
    }

    $headers = ['Accept: ' . $accept];
    if ($rawBody !== null) {
        $headers[] = 'Content-Type: ' . $contentType;
    }

    curl_setopt_array($curl, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_USERPWD => $login . ':' . $password,
        CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_CUSTOMREQUEST => $method,
    ]);

    if ($rawBody !== null) {
        curl_setopt($curl, CURLOPT_POSTFIELDS, $rawBody);
    }

    $body = curl_exec($curl);
    $status = (int) curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    $error = curl_error($curl);
    curl_close($curl);

    return [
        'status' => $status,
        'body' => is_string($body) ? $body : '',
        'error' => $error,
    ];
}

function toJson(mixed $value): string
{
    $json = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
    return $json === false ? '[json_encode error]' : $json;
}

function printResponse(string $label, array $response): void
{
    echo $label . PHP_EOL;
    echo 'HTTP: ' . $response['status'] . PHP_EOL;
    if ($response['error'] !== '') {
        echo 'cURL error: ' . $response['error'] . PHP_EOL;
    }
    if ($response['body'] === '') {
        echo "BODY: [empty]\n\n";
        return;
    }

    $decoded = json_decode($response['body'], true);
    if (is_array($decoded)) {
        echo "BODY:\n" . toJson($decoded) . PHP_EOL;
        if (!empty($decoded['errors'])) {
            echo "ERRORS:\n" . toJson($decoded['errors']) . PHP_EOL;
        }
    } else {
        echo "BODY:\n" . $response['body'] . PHP_EOL;
    }
    echo PHP_EOL;
}

function putProduct(string $gtin, array $attributes, string $login, string $password): array
{
    $payload = [
        'data' => [
            'type' => 'products',
            'id' => $gtin,
            'attributes' => $attributes,
        ],
    ];

    return gs1Request(
        'PUT',
        GS1_BASE . '/products/' . rawurlencode($gtin),
        $login,
        $password,
        json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
    );
}

echo "=== GS1 Diagnostic v5 ===\n";
echo "Target GTIN: {$targetGtin}\n\n";

// 1) Check target GTIN
$targetGet = gs1Request('GET', GS1_BASE . '/products/' . rawurlencode($targetGtin), $login, $password);
printResponse('--- Step 1: GET target GTIN ---', $targetGet);

// 2) PUT with values aligned to external API swagger example (language as `pl`)
$attrsSwaggerLike = [
    'brandName' => 'Test Marka',
    'subBrandName' => 'Test Podmarka',
    'commonName' => 'Test produkt',
    'name' => 'Test produkt API',
    'description' => 'Test opisu produktu',
    'gpcCode' => 10000002,
    'netContent' => 1.5,
    'netContentUnit' => 'kg',
    'status' => 'ACT',
    'targetMarket' => ['PL'],
    'descriptionLanguage' => 'pl',
];
$putTargetSwaggerLike = putProduct($targetGtin, $attrsSwaggerLike, $login, $password);
printResponse('--- Step 2: PUT target GTIN (swagger-like payload) ---', $putTargetSwaggerLike);

// 3) PUT with original app defaults (for direct comparison with old script behavior)
$attrsAppLike = [
    'brandName' => 'marianek.pl',
    'subBrandName' => 'marianek.pl',
    'commonName' => 'Produkt testowy',
    'name' => 'Produkt testowy API',
    'gpcCode' => 10008365,
    'netContent' => 1,
    'netContentUnit' => 'szt',
    'status' => 'ACT',
    'targetMarket' => ['PL'],
    'descriptionLanguage' => 'PL',
];
$putTargetAppLike = putProduct($targetGtin, $attrsAppLike, $login, $password);
printResponse('--- Step 3: PUT target GTIN (app-like payload) ---', $putTargetAppLike);

// 4) Permission check: read an existing product and try no-op PUT.
$list = gs1Request('GET', GS1_BASE . '/products?page[offset]=1&page[limit]=1&sort=name', $login, $password);
printResponse('--- Step 4a: GET list (first product) ---', $list);

$existingGtin = null;
$existingAttributes = null;
$listDecoded = json_decode($list['body'], true);
if (is_array($listDecoded) && isset($listDecoded['data'][0]['id'])) {
    $existingGtin = (string) $listDecoded['data'][0]['id'];
    $existingAttributes = $listDecoded['data'][0]['attributes'] ?? null;
}

if ($existingGtin !== null && is_array($existingAttributes)) {
    $noOpPut = putProduct($existingGtin, $existingAttributes, $login, $password);
    printResponse('--- Step 4b: PUT existing product with attributes from GET (no-op) ---', $noOpPut);
} else {
    echo "--- Step 4b: skipped (no product data from list) ---\n\n";
}

echo "=== DONE ===\n";
