<?php

use App\Models\SettingsCatalogCategory;
use App\Models\SettingsCatalogDefinition;
use App\Services\Intune\PolicyNormalizer;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

beforeEach(function () {
    $this->normalizer = app(PolicyNormalizer::class);
});

it('flattens settings catalog setting instances into a table', function () {
    $snapshot = [
        '@odata.type' => '#microsoft.graph.deviceManagementConfigurationPolicy',
        'settings' => [
            [
                'id' => 's1',
                'settingInstance' => [
                    '@odata.type' => '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance',
                    'settingDefinitionId' => 'device_vendor_msft_policy_config_system_minimumpinlength',
                    'simpleSettingValue' => [
                        '@odata.type' => '#microsoft.graph.deviceManagementConfigurationIntegerSettingValue',
                        'value' => 12,
                    ],
                ],
            ],
            [
                'id' => 's2',
                'settingInstance' => [
                    '@odata.type' => '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance',
                    'settingDefinitionId' => 'device_vendor_msft_policy_config_system_usebiometrics',
                    'choiceSettingValue' => [
                        'value' => 'device_vendor_msft_policy_config_system_usebiometrics_true',
                    ],
                ],
            ],
            [
                'id' => 'group',
                'settingInstance' => [
                    '@odata.type' => '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance',
                    'settingDefinitionId' => 'device_vendor_msft_policy_config_system_group',
                    'groupSettingCollectionValue' => [
                        [
                            'children' => [
                                [
                                    '@odata.type' => '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance',
                                    'settingDefinitionId' => 'device_vendor_msft_policy_config_system_child',
                                    'simpleSettingValue' => [
                                        'value' => true,
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
            [
                'id' => 'unknown',
                'settingInstance' => [
                    '@odata.type' => '#microsoft.graph.someUnknownSettingInstance',
                    'settingDefinitionId' => 'unknown_definition',
                    'foo' => 'bar',
                ],
            ],
        ],
    ];

    $result = $this->normalizer->normalize($snapshot, 'settingsCatalogPolicy', 'windows');

    expect($result['status'])->toBe('success');
    expect($result)->toHaveKey('settings_table');

    $rows = collect($result['settings_table']['rows']);

    // Use definition_id field for lookup (raw ID), definition field now contains display name
    $minimumPinLength = $rows->firstWhere('definition_id', 'device_vendor_msft_policy_config_system_minimumpinlength');
    expect($minimumPinLength)->not->toBeNull();
    expect($minimumPinLength['definition'])->toContain('Minimum'); // Display name
    expect($minimumPinLength['data_type'])->toBe('Number'); // User-friendly type
    expect($minimumPinLength['value'])->toBe('12');
    expect($minimumPinLength)->toHaveKey('category');
    expect($minimumPinLength)->toHaveKey('description');

    $useBiometrics = $rows->firstWhere('definition_id', 'device_vendor_msft_policy_config_system_usebiometrics');
    expect($useBiometrics)->not->toBeNull();
    expect($useBiometrics['definition'])->toContain('Usebiometrics'); // Display name (prettified)
    expect($useBiometrics['value'])->toBe('Enabled'); // Formatted from "usebiometrics_true" -> "Enabled"

    $child = $rows->firstWhere('definition_id', 'device_vendor_msft_policy_config_system_child');
    expect($child)->not->toBeNull();
    expect($child['definition'])->toContain('Child'); // Display name (prettified)
    expect($child['value'])->toBe('Enabled'); // Formatted from boolean true -> "Enabled"
    expect($child['path'])->toContain('group'); // Path contains parent definition IDs

    $unknown = $rows->firstWhere('definition_id', 'unknown_definition');
    expect($unknown)->not->toBeNull();
    expect($unknown['definition'])->toBe('Unknown Definition'); // Prettified fallback
    expect($unknown['value'])->toContain('foo');
});

it('inherits category from nearest ancestor when child categories are missing', function () {
    $categoryId = 'cat-windows-hello';
    $parentDefinitionId = 'device_vendor_msft_passportforwork_biometrics_usebiometrics';
    $groupDefinitionId = 'device_vendor_msft_passportforwork_{tenantid}';
    $childDefinitionId = 'device_vendor_msft_passportforwork_{tenantid}_policies_pincomplexity_expiration';

    SettingsCatalogCategory::create([
        'category_id' => $categoryId,
        'display_name' => 'Windows Hello For Business',
        'description' => 'Windows Hello settings',
    ]);

    SettingsCatalogDefinition::create([
        'definition_id' => $parentDefinitionId,
        'display_name' => 'Allow Use of Biometrics',
        'description' => 'Enable biometrics',
        'category_id' => $categoryId,
        'raw' => ['id' => $parentDefinitionId],
    ]);

    $snapshot = [
        '@odata.type' => '#microsoft.graph.deviceManagementConfigurationPolicy',
        'settings' => [
            [
                'id' => '0',
                'settingInstance' => [
                    '@odata.type' => '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance',
                    'settingDefinitionId' => $parentDefinitionId,
                    'choiceSettingValue' => [
                        'value' => "{$parentDefinitionId}_true",
                        'children' => [
                            [
                                '@odata.type' => '#microsoft.graph.deviceManagementConfigurationGroupSettingInstance',
                                'settingDefinitionId' => $groupDefinitionId,
                                'groupSettingValue' => [
                                    'children' => [
                                        [
                                            '@odata.type' => '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance',
                                            'settingDefinitionId' => $childDefinitionId,
                                            'simpleSettingValue' => [
                                                'value' => 0,
                                            ],
                                        ],
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ],
    ];

    $result = $this->normalizer->normalize($snapshot, 'settingsCatalogPolicy', 'windows');

    $rows = collect($result['settings_table']['rows']);
    $group = $rows->firstWhere('definition_id', $groupDefinitionId);
    $child = $rows->firstWhere('definition_id', $childDefinitionId);

    expect($group)->not->toBeNull();
    expect($child)->not->toBeNull();
    expect($group['category'])->toBe('Windows Hello For Business');
    expect($child['category'])->toBe('Windows Hello For Business');
});

it('uses the only known category for template settings without ancestors', function () {
    $categoryId = 'cat-windows-hello';
    $rootDefinitionId = 'device_vendor_msft_passportforwork_biometrics_usebiometrics';
    $groupDefinitionId = 'device_vendor_msft_passportforwork_{tenantid}';
    $childDefinitionId = 'device_vendor_msft_passportforwork_{tenantid}_policies_pincomplexity_expiration';

    SettingsCatalogCategory::create([
        'category_id' => $categoryId,
        'display_name' => 'Windows Hello For Business',
        'description' => 'Windows Hello settings',
    ]);

    SettingsCatalogDefinition::create([
        'definition_id' => $rootDefinitionId,
        'display_name' => 'Allow Use of Biometrics',
        'description' => 'Enable biometrics',
        'category_id' => $categoryId,
        'raw' => ['id' => $rootDefinitionId],
    ]);

    $snapshot = [
        '@odata.type' => '#microsoft.graph.deviceManagementConfigurationPolicy',
        'settings' => [
            [
                'id' => 'root',
                'settingInstance' => [
                    '@odata.type' => '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance',
                    'settingDefinitionId' => $rootDefinitionId,
                    'choiceSettingValue' => [
                        'value' => "{$rootDefinitionId}_true",
                    ],
                ],
            ],
            [
                'id' => 'group',
                'settingInstance' => [
                    '@odata.type' => '#microsoft.graph.deviceManagementConfigurationGroupSettingInstance',
                    'settingDefinitionId' => $groupDefinitionId,
                    'groupSettingValue' => [
                        'children' => [
                            [
                                '@odata.type' => '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance',
                                'settingDefinitionId' => $childDefinitionId,
                                'simpleSettingValue' => [
                                    'value' => 0,
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ],
    ];

    $result = $this->normalizer->normalize($snapshot, 'settingsCatalogPolicy', 'windows');

    $rows = collect($result['settings_table']['rows']);
    $group = $rows->firstWhere('definition_id', $groupDefinitionId);
    $child = $rows->firstWhere('definition_id', $childDefinitionId);

    expect($group)->not->toBeNull();
    expect($child)->not->toBeNull();
    expect($group['category'])->toBe('Windows Hello For Business');
    expect($child['category'])->toBe('Windows Hello For Business');
});
