<?php

declare(strict_types=1);

/**
 * Regenerates the canonical Postman collection from Laravel's registered routes.
 *
 * Run from the backend root with:
 *   php postman/generate-shopit-collection.php
 */
$root = dirname(__DIR__);
chdir($root);

$command = escapeshellarg(PHP_BINARY).' artisan route:list --path=api --json';
$routeJson = shell_exec($command);

if (! is_string($routeJson) || trim($routeJson) === '') {
    fwrite(STDERR, "Unable to read Laravel routes.\n");
    exit(1);
}

$routes = json_decode($routeJson, true, flags: JSON_THROW_ON_ERROR);

const TINY_PNG = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';

/** @return array<string, mixed> */
function jsonBody(array $payload): array
{
    $raw = json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    $raw = preg_replace('/"\{\{([a-z_]+_id)\}\}"/', '{{$1}}', $raw);

    return [
        'mode' => 'raw',
        'raw' => $raw,
        'options' => ['raw' => ['language' => 'json']],
    ];
}

/** @param array<string, string> $fields
 * @return array<string, mixed>
 */
function formDataBody(array $fields, array $fileFields = []): array
{
    $formData = [];

    foreach ($fields as $key => $value) {
        $formData[] = ['key' => $key, 'value' => $value, 'type' => 'text'];
    }

    foreach ($fileFields as $key) {
        $formData[] = ['key' => $key, 'type' => 'file', 'src' => []];
    }

    return ['mode' => 'formdata', 'formdata' => $formData];
}

/** @return array<string, mixed>|null */
function bodyFor(string $method, string $uri): ?array
{
    $key = $method.' '.$uri;

    $exact = [
        'POST api/auth/google/exchange' => ['oauth_code' => '{{oauth_code}}', 'tenant_codigo' => '{{tenant_code}}'],
        'POST api/register' => ['tenant_codigo' => '{{tenant_code}}', 'nombre_apellido' => 'Usuario Demo', 'email' => '{{user_email}}', 'password' => '{{user_password}}', 'password_confirmation' => '{{user_password}}', 'dni' => '30123456', 'telefono' => '+5491112345678'],
        'POST api/login' => ['email' => '{{user_email}}', 'password' => '{{user_password}}', 'tenant_codigo' => '{{tenant_code}}'],
        'PUT api/me' => ['nombre_apellido' => 'Usuario Demo Actualizado', 'email' => '{{user_email}}', 'dni' => '30123456', 'telefono' => '+5491112345678'],
        'POST api/password/reset-attempts' => ['tenant_codigo' => '{{tenant_code}}', 'email' => '{{user_email}}'],
        'POST api/password/reset-attempts/validate' => ['email' => '{{user_email}}', 'codigo' => '{{reset_code}}'],
        'POST api/password/reset' => ['email' => '{{user_email}}', 'codigo' => '{{reset_code}}', 'password' => '{{user_password}}', 'password_confirmation' => '{{user_password}}'],
        'POST api/clients' => ['code' => 'cliente-demo', 'name' => 'Cliente Demo'],
        'PUT api/clients/{client}' => ['code' => 'cliente-demo', 'name' => 'Cliente Demo Actualizado'],
        'PATCH api/clients/{client}' => ['name' => 'Cliente Demo Actualizado'],
        'POST api/integrations' => ['integration_code' => 'telepagos', 'name' => 'Telepagos', 'url' => 'https://api.example.com', 'integration_data_schema' => ['api_key' => ['required', 'string']], 'requires_client_configuration' => true],
        'PUT api/integrations/{integration}' => ['name' => 'Telepagos', 'url' => 'https://api.example.com', 'requires_client_configuration' => true],
        'PUT api/clients/{client}/integrations/{integration_code}' => ['integration_data' => ['api_key' => 'replace-me']],
        'POST api/menues' => ['code' => 'demo', 'label' => 'Demo', 'parent_menu_code' => null, 'content_type' => 'static', 'static_content_schema' => ['title' => ['required', 'string']], 'route' => '/demo'],
        'PUT api/menues/{menue}' => ['label' => 'Demo actualizado', 'route' => '/demo'],
        'PATCH api/menues/{menue}' => ['label' => 'Demo actualizado'],
        'POST api/{tenant_code}/menues/{menu_code}' => ['static_content' => ['title' => 'Contenido demo']],
        'POST api/webhooks/telepagos/{client}' => ['id' => 'payment-id-demo'],
        'POST api/{tenant_code}/mail-test/send' => ['to' => 'destinatario@example.com', 'subject' => 'Prueba ShopIt', 'message' => 'Correo de prueba enviado desde Postman.'],
        'POST api/tenants/{tenant:codigo}/cart/items' => ['catalog_item_id' => '{{catalog_item_id}}', 'variant_id' => '{{variant_id}}', 'cantidad' => 1],
        'PATCH api/tenants/{tenant:codigo}/cart/items/{cartItem}' => ['cantidad' => 2, 'variant_id' => '{{variant_id}}'],
        'POST api/tenants/{tenant:codigo}/catalog-items/{catalogItem}/variant-options' => ['selected_values' => ['color' => 'azul'], 'cart_item_id' => '{{cart_item_id}}'],
        'POST api/tenants/{tenant:codigo}/compras/start-checkout' => ['cart_id' => '{{cart_id}}'],
        'PATCH api/tenants/{tenant:codigo}/compras/{compra}/customer-data' => ['dni' => '30123456', 'telefono' => '+5491112345678', 'nombre_apellido' => 'Usuario Demo', 'email' => '{{user_email}}'],
        'PATCH api/tenants/{tenant:codigo}/compras/{compra}/items/{item}' => ['quantity' => 2, 'variant_id' => '{{variant_id}}'],
        'POST api/tenants/{tenant:codigo}/compras/{compra}/payment-intent' => ['method' => 'transfer', 'transfer_payer_dni' => '30123456'],
        'POST api/tenants/{tenant:codigo}/tickets/pdf' => ['ticket_ids' => [1]],
        'POST api/v1/adminapp/login' => ['email' => '{{admin_email}}', 'password' => '{{admin_password}}'],
        'POST api/v1/adminapp/password/reset-attempts' => ['email' => '{{admin_email}}'],
        'POST api/v1/adminapp/password/reset-attempts/validate' => ['email' => '{{admin_email}}', 'codigo' => '{{reset_code}}'],
        'POST api/v1/adminapp/password/reset' => ['email' => '{{admin_email}}', 'codigo' => '{{reset_code}}', 'password' => '{{admin_password}}', 'password_confirmation' => '{{admin_password}}'],
        'PUT api/v1/adminapp/tenant/event' => ['title' => 'Evento Demo', 'location' => 'Buenos Aires', 'dates' => [['date' => '2026-12-01', 'start_time' => '18:00', 'end_time' => '23:00']], 'social_media' => [['code' => 'instagram', 'url' => 'https://instagram.com/example', 'orden' => 0]]],
        'POST api/v1/adminapp/tenant/featured-groups' => ['category_name' => 'Destacados', 'is_featured' => true],
        'PUT api/v1/adminapp/tenant/featured-groups/{featuredGroup}' => ['category_name' => 'Destacados', 'is_featured' => true],
        'POST api/v1/adminapp/tenant/staff' => ['nombre_apellido' => 'Operador Demo', 'dni' => '30123456', 'email' => 'operador@example.com', 'category_ids' => [1]],
        'PUT api/v1/adminapp/tenant/staff/{staff}' => ['nombre_apellido' => 'Operador Demo', 'dni' => '30123456', 'email' => 'operador@example.com', 'category_ids' => [1]],
        'PATCH api/v1/adminapp/tenant/staff/{staff}' => ['nombre_apellido' => 'Operador Demo', 'dni' => '30123456', 'email' => 'operador@example.com', 'category_ids' => [1]],
        'PUT api/v1/adminapp/tenant/website-extras/{websiteExtraCode}' => ['enabled' => true, 'content' => ['title' => 'Contenido demo']],
        'PATCH api/v1/adminapp/tenant/website-extras/{websiteExtraCode}/toggle' => ['enabled' => true],
        'POST api/v1/adminapp/tenant/accommodations' => ['variants' => [['title' => 'Habitación doble', 'description' => 'Dos personas', 'stock' => 10, 'price' => 100000]]],
        'POST api/v1/adminapp/tenant/entries' => ['entries' => [['title' => 'Entrada general', 'description' => 'Acceso general', 'event_date_ids' => [1], 'stock' => 100, 'price' => 25000]]],
        'POST api/v1/adminapp/tenant/foods' => ['variants' => [['event_date_id' => 1, 'schedule' => '21:00', 'service' => 'Cena', 'description' => 'Menú completo', 'stock' => 100, 'price' => 15000]]],
        'POST api/v1/adminapp/tenant/merchandise' => ['items' => [['title' => 'Camiseta', 'description' => 'Camiseta oficial', 'max_units_per_user' => 2, 'variants' => [['color' => 'Azul', 'size' => 'M', 'stock' => 20, 'price' => 30000]]]]],
        'PUT api/v1/adminapp/tenant/desfile/entries' => ['rows' => [['type' => 'General', 'sector' => 'A', 'row' => 1, 'max_seat' => 20, 'price' => 25000]]],
        'PATCH api/v1/adminapp/tenant/desfile/entries/image' => ['is_enabled' => true],
        'POST api/v1/scanner/login' => ['email' => '{{scanner_email}}', 'password' => '{{scanner_password}}'],
        'POST api/v1/scanner/password/reset-attempts' => ['email' => '{{scanner_email}}'],
        'POST api/v1/scanner/password/reset-attempts/validate' => ['email' => '{{scanner_email}}', 'codigo' => '{{reset_code}}'],
        'POST api/v1/scanner/password/reset' => ['email' => '{{scanner_email}}', 'codigo' => '{{reset_code}}', 'password' => '{{scanner_password}}', 'password_confirmation' => '{{scanner_password}}'],
    ];

    if (isset($exact[$key])) {
        return jsonBody($exact[$key]);
    }

    if ($key === 'POST api/tenants') {
        return jsonBody([
            'client_id' => '{{client_id}}',
            'codigo' => '{{tenant_code}}',
            'nombre' => 'Tenant Demo',
            'dominio' => '{{tenant_domain}}',
            'site_title' => 'ShopIt Demo',
            'primary_color' => '#111827',
            'secondary_color' => '#2563EB',
            'danger_color' => '#DC2626',
            'success_color' => '#16A34A',
            'header_bg_color' => '#FFFFFF',
            'footer_bg_color' => '#111827',
            'header_logo' => TINY_PNG,
            'footer_logo' => TINY_PNG,
            'search_product_layout' => 'column_with_image',
            'search_group_layout' => 'paginated',
            'search_items_per_page' => 12,
            'display_categories' => true,
            'display_seach_bar' => true,
            'display_cart' => true,
            'cart_editing_policy' => 'full',
            'website_type_code' => 'shopit',
        ]);
    }

    if (in_array($key, ['PUT api/tenants/{tenant}', 'PATCH api/tenants/{tenant}'], true)) {
        return jsonBody(['nombre' => 'Tenant Demo Actualizado', 'site_title' => 'ShopIt Demo', 'primary_color' => '#111827', 'cart_editing_policy' => 'full']);
    }

    if ($key === 'POST api/tenants/{tenant:codigo}/catalog-items') {
        return jsonBody([
            'type' => 'standard',
            'category_id' => '{{category_id}}',
            'slug' => 'producto-demo',
            'nombre' => 'Producto Demo',
            'descripcion' => 'Producto creado desde Postman',
            'precio' => 10000,
            'inventory_policy' => 'tracked',
            'inventory_subject' => 'product',
            'max_units_per_user' => 5,
            'has_tickets' => false,
            'real_stock' => 100,
            'images' => [TINY_PNG],
        ]);
    }

    if ($key === 'POST api/storage-test/s3/upload') {
        return formDataBody(['path' => 'postman/test-file.png', 'expires_in_minutes' => '60'], ['file']);
    }

    if ($key === 'POST api/v1/adminapp/tenant/desfile/entries/image') {
        return formDataBody(['is_enabled' => '1'], ['image']);
    }

    return null;
}

/** @return array<int, array{key: string, value: string, disabled?: bool}> */
function queryFor(string $uri): array
{
    return match ($uri) {
        'api/tenants/bootstrap' => [['key' => 'dominio', 'value' => '{{tenant_domain}}'], ['key' => 'path', 'value' => '/']],
        'api/v1/adminapp/bootstrap/{dominio}', 'api/v1/scanner/bootstrap/{dominio}' => [['key' => 'path', 'value' => '/']],
        'api/tenants/{tenant:codigo}/catalog-items' => [['key' => 'q', 'value' => 'demo'], ['key' => 'page', 'value' => '1']],
        'api/tenants/{tenant:codigo}/catalog-items/{catalogItem}' => [['key' => 'variant_id', 'value' => '{{variant_id}}', 'disabled' => true]],
        'api/tenants/{tenant:codigo}/catalog/featured-groups/{featuredGroup}/items',
        'api/tenants/{tenant:codigo}/categories/{category}' => [['key' => 'page', 'value' => '1']],
        'api/tenants/{tenant:codigo}/compras' => [['key' => 'status', 'value' => 'pending_payment', 'disabled' => true], ['key' => 'page', 'value' => '1']],
        'api/v1/adminapp/tenant/sales', 'api/v1/adminapp/tenant/sales/pdf' => [
            ['key' => 'q', 'value' => '', 'disabled' => true],
            ['key' => 'status', 'value' => 'confirmed', 'disabled' => true],
            ['key' => 'sale_date', 'value' => '2026-12-01', 'disabled' => true],
            ['key' => 'sort_by', 'value' => 'date'],
            ['key' => 'sort_direction', 'value' => 'desc'],
            ['key' => 'page', 'value' => '1'],
            ['key' => 'per_page', 'value' => '20'],
        ],
        'api/v1/scanner/tickets' => [['key' => 'q', 'value' => '', 'disabled' => true], ['key' => 'page', 'value' => '1'], ['key' => 'per_page', 'value' => '20']],
        'api/storage-test/s3/temporary-url' => [['key' => 'path', 'value' => '{{s3_path}}'], ['key' => 'expires_in_minutes', 'value' => '60']],
        default => [],
    };
}

/** @return array{0: string, 1: string} */
function folderFor(string $uri, string $action): array
{
    preg_match('/App\\\\Domains\\\\([^\\\\]+)/', $action, $matches);
    $domain = $matches[1] ?? 'Other';

    if (str_starts_with($uri, 'api/v1/adminapp/')) {
        return ['Admin App API', $domain];
    }

    if (str_starts_with($uri, 'api/v1/scanner/')) {
        return ['Scanner API', $domain];
    }

    if (str_starts_with($uri, 'api/webhooks/')) {
        return ['Webhooks', $domain];
    }

    if (in_array($domain, ['StorageTest', 'MailTest'], true)) {
        return ['Developer Utilities', $domain];
    }

    if (in_array($domain, ['Client', 'Integration', 'Menu', 'Tenant'], true) && ! str_contains($uri, '{tenant:codigo}')) {
        return ['Platform Management', $domain];
    }

    return ['Storefront API', $domain];
}

function humanize(string $value): string
{
    $value = preg_replace('/Controller$/', '', $value);
    $value = preg_replace('/(?<!^)[A-Z]/', ' $0', (string) $value);

    return trim(str_replace(['_', '-'], ' ', (string) $value));
}

function requestName(string $method, string $action, bool $multiMethod): string
{
    $parts = explode('\\', explode('@', $action)[0]);
    $controller = humanize(end($parts));
    $handler = str_contains($action, '@') ? explode('@', $action)[1] : '__invoke';
    $verbs = [
        'index' => 'List', 'store' => 'Create', 'show' => 'Get', 'update' => 'Update',
        'destroy' => 'Delete', 'addItem' => 'Add Item', 'updateItemQuantity' => 'Update Item Quantity',
        'updateItem' => 'Update Item',
        'removeItem' => 'Remove Item', 'search' => 'Search', 'category' => 'Get Category',
        'featuredGroupItems' => 'List Featured Group Items', 'variantOptions' => 'Get Variant Options',
        'startCheckout' => 'Start Checkout', 'updateCustomerData' => 'Update Customer Data',
        'paymentIntent' => 'Create Payment Intent',
        'submitForReview' => 'Submit for Review', 'cancel' => 'Cancel', 'complete' => 'Complete',
        'downloadPdf' => 'Download PDF', 'downloadModificationsPdf' => 'Download Modifications PDF',
        'modifications' => 'List Modifications', 'tickets' => 'List Tickets', 'confirm' => 'Confirm',
        'temporaryUrl' => 'Generate Temporary URL', 'replaceImage' => 'Replace Image',
        'updateImage' => 'Update Image', 'destroyImage' => 'Delete Image', 'showExtra' => 'Get Extra',
        'toggle' => 'Toggle', 'scan' => 'Scan', 'handle' => 'Receive',
    ];

    $name = $handler === '__invoke'
        ? $controller
        : (($verbs[$handler] ?? humanize($handler)).' '.$controller);

    return $multiMethod ? $name.' ('.$method.')' : $name;
}

function pathFor(string $uri): string
{
    $variables = [
        'tenant:codigo' => 'tenant_code', 'tenant' => 'tenant_id', 'client' => 'client_id',
        'integration_code' => 'integration_code', 'integration' => 'integration_id', 'menue' => 'menu_id',
        'menu_code' => 'menu_code', 'tenant_code' => 'tenant_code', 'catalogItem' => 'catalog_item_id',
        'featuredGroup' => 'featured_group_id', 'category' => 'category_id', 'cartItem' => 'cart_item_id',
        'compra' => 'purchase_id', 'item' => 'purchase_item_id', 'dominio' => 'tenant_domain',
        'sale' => 'sale_id', 'staff' => 'staff_id', 'websiteExtraCode' => 'website_extra_code',
        'accommodation' => 'accommodation_id', 'entry' => 'entry_id', 'food' => 'food_id',
        'merchandise' => 'merchandise_id', 'ticketUuid' => 'ticket_uuid',
    ];

    return preg_replace_callback('/\{([^}]+)\}/', function (array $matches) use ($variables): string {
        $variable = $variables[$matches[1]] ?? strtolower((string) preg_replace('/(?<!^)[A-Z]/', '_$0', $matches[1]));

        return '{{'.$variable.'}}';
    }, $uri);
}

/** @return array<string, mixed> */
function authFor(string $uri, array $middleware): ?array
{
    $protected = count(array_filter(
        $middleware,
        fn (string $item): bool => str_contains($item, 'Authenticate:sanctum'),
    )) > 0;

    if (! $protected) {
        return null;
    }

    $variable = str_starts_with($uri, 'api/v1/adminapp/')
        ? 'admin_token'
        : (str_starts_with($uri, 'api/v1/scanner/') ? 'scanner_token' : 'token');

    return ['type' => 'bearer', 'bearer' => [['key' => 'token', 'value' => '{{'.$variable.'}}', 'type' => 'string']]];
}

/** @return array<string, mixed> */
function tokenCaptureEvent(string $uri): array
{
    $variable = $uri === 'api/v1/adminapp/login' ? 'admin_token' : ($uri === 'api/v1/scanner/login' ? 'scanner_token' : 'token');

    return [
        'listen' => 'test',
        'script' => [
            'type' => 'text/javascript',
            'exec' => [
                'if (pm.response.code >= 200 && pm.response.code < 300) {',
                '  const payload = pm.response.json();',
                "  if (payload.token) pm.collectionVariables.set('{$variable}', payload.token);",
                '}',
            ],
        ],
    ];
}

$tree = [];
$registeredOperations = 0;

foreach ($routes as $route) {
    $methods = array_values(array_filter(explode('|', $route['method']), fn (string $method): bool => $method !== 'HEAD'));
    $multiMethod = count($methods) > 1;

    foreach ($methods as $method) {
        [$section, $folder] = folderFor($route['uri'], $route['action']);
        $path = pathFor($route['uri']);
        $query = queryFor($route['uri']);
        $enabledQuery = array_values(array_filter($query, fn (array $item): bool => ! ($item['disabled'] ?? false)));
        $queryString = $enabledQuery === [] ? '' : '?'.implode('&', array_map(
            fn (array $item): string => rawurlencode($item['key']).'='.$item['value'],
            $enabledQuery,
        ));
        $body = bodyFor($method, $route['uri']);
        $auth = authFor($route['uri'], $route['middleware']);
        $headers = [['key' => 'Accept', 'value' => 'application/json', 'type' => 'text']];

        if (($body['mode'] ?? null) === 'raw') {
            $headers[] = ['key' => 'Content-Type', 'value' => 'application/json', 'type' => 'text'];
        }

        $request = [
            'method' => $method,
            'header' => $headers,
            'description' => sprintf(
                "Ruta Laravel: `%s /%s`\n\nControlador: `%s`%s",
                $method,
                $route['uri'],
                $route['action'],
                $auth === null ? '' : "\n\nRequiere autenticación Sanctum.",
            ),
            'url' => [
                'raw' => '{{base_url}}/'.$path.$queryString,
                'host' => ['{{base_url}}'],
                'path' => explode('/', $path),
            ],
        ];

        if ($query !== []) {
            $request['url']['query'] = $query;
        }

        if ($body !== null) {
            $request['body'] = $body;
        }

        if ($auth !== null) {
            $request['auth'] = $auth;
        }

        $item = [
            'name' => requestName($method, $route['action'], $multiMethod),
            'request' => $request,
            'response' => [],
        ];

        if (in_array($route['uri'], ['api/login', 'api/v1/adminapp/login', 'api/v1/scanner/login'], true)) {
            $item['event'] = [tokenCaptureEvent($route['uri'])];
        }

        $tree[$section][$folder][] = $item;
        $registeredOperations++;
    }
}

$sectionDescriptions = [
    'Storefront API' => 'API pública y autenticada consumida por el storefront: autenticación, catálogo, carrito, compras y tickets.',
    'Admin App API' => 'Operaciones de administración del tenant. Ejecutá Login primero para completar `admin_token`.',
    'Scanner API' => 'Operaciones de la aplicación de escaneo. Ejecutá Login primero para completar `scanner_token`.',
    'Platform Management' => 'CRUD y configuración de tenants, clientes, menús e integraciones.',
    'Webhooks' => 'Entradas públicas para notificaciones de proveedores externos.',
    'Developer Utilities' => 'Endpoints de diagnóstico de correo y almacenamiento. No deberían exponerse en producción.',
];

$items = [];
foreach ($tree as $section => $folders) {
    $children = [];
    foreach ($folders as $folder => $requests) {
        $children[] = ['name' => humanize($folder), 'item' => $requests];
    }

    $items[] = [
        'name' => $section,
        'description' => $sectionDescriptions[$section] ?? '',
        'item' => $children,
    ];
}

$variables = [
    'base_url' => 'http://localhost:8000',
    'token' => '', 'admin_token' => '', 'scanner_token' => '',
    'user_email' => 'usuario@example.com', 'user_password' => 'Password!123',
    'admin_email' => 'admin@example.com', 'admin_password' => 'Password!123',
    'scanner_email' => 'scanner@example.com', 'scanner_password' => 'Password!123',
    'tenant_code' => 'demo', 'tenant_id' => '1', 'tenant_domain' => 'demo.test',
    'client_id' => '1', 'integration_id' => '1', 'integration_code' => 'telepagos',
    'menu_id' => '1', 'menu_code' => 'demo', 'catalog_item_id' => '1', 'variant_id' => '1',
    'category_id' => '1', 'featured_group_id' => '1', 'cart_id' => '1', 'cart_item_id' => '1',
    'purchase_id' => '1', 'purchase_item_id' => '1', 'sale_id' => '1', 'staff_id' => '1',
    'website_extra_code' => 'hero', 'accommodation_id' => '1', 'entry_id' => '1', 'food_id' => '1',
    'merchandise_id' => '1', 'ticket_uuid' => '00000000-0000-0000-0000-000000000000',
    'oauth_code' => '00000000-0000-0000-0000-000000000000', 'reset_code' => '1234',
    's3_path' => 'postman/test-file.png',
];

$collection = [
    'info' => [
        '_postman_id' => '76fd6fd2-53b9-4d92-8e02-1ddcc6207fa2',
        'name' => 'ShopIt API — Complete',
        'description' => "Colección canónica generada desde las rutas reales de Laravel. Incluye {$registeredOperations} operaciones HTTP, ejemplos de payload, filtros, archivos y tokens separados para Storefront, Admin App y Scanner.\n\nUso rápido:\n1. Ajustá `base_url` y las credenciales.\n2. Ejecutá el Login de la aplicación correspondiente; el token se guarda automáticamente.\n3. Ajustá los IDs y códigos de las variables de colección.\n\nRegeneración: `php postman/generate-shopit-collection.php`.",
        'schema' => 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json',
    ],
    'item' => $items,
    'variable' => array_map(
        fn (string $key, string $value): array => ['key' => $key, 'value' => $value, 'type' => 'string'],
        array_keys($variables),
        array_values($variables),
    ),
];

$output = $root.DIRECTORY_SEPARATOR.'ShopIt_API_Postman_Collection.json';
file_put_contents($output, json_encode($collection, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).PHP_EOL);

fwrite(STDOUT, "Generated {$registeredOperations} operations in {$output}\n");
