<?php

declare(strict_types=1);

usesApiSuite();

it('creates lists and updates complete branding values', function (): void {
    api_test_covers('GET /branding', 'happy');
    api_test_covers('POST /branding', 'happy');
    api_test_covers('PUT /branding', 'happy');

    $session = api_fixtures()->createUserSession([
        'list_branding_options',
        'add_branding_option',
        'edit_branding_option',
    ]);

    $createPayload = [
        'name' => 'API Brand ' . uniqid('', false),
        'description' => 'Created through the branding API',
        'cvr' => 41004355,
        'address' => 'Skagerrakvej 15, 6715 Esbjerg',
        'phone_country_code' => 45,
        'phone' => 76123456,
        'email' => 'brand@example.test',
        'website' => 'https://brand.example.test',
        'banner' => 'https://cdn.example.test/banner.png',
        'logo' => 'https://cdn.example.test/logo.png',
        'favicon' => 'https://cdn.example.test/favicon.ico',
        'signature' => 'https://cdn.example.test/signature.png',
    ];

    $createResponse = api_client()->post('/branding', $createPayload, $session['headers']);

    $createResponse
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();

    $createdId = (int)($createResponse->data()['id'] ?? 0);
    expect($createdId)->toBeGreaterThan(0);
    api_fixtures()->cleanupDeleteById('branding', $createdId);

    $singleResponse = api_client()->get('/branding?id=' . $createdId, $session['headers']);

    $singleResponse
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();

    expect($singleResponse->data())
        ->toBeArray()
        ->toHaveKey('id', $createdId)
        ->toHaveKey('name', $createPayload['name'])
        ->toHaveKey('logo', $createPayload['logo']);

    $listResponse = api_client()->get('/branding', $session['headers']);

    $listResponse
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();

    $listedIds = array_map(
        static fn(array $branding): int => (int)($branding['id'] ?? 0),
        is_array($listResponse->data()) ? $listResponse->data() : []
    );
    expect($listedIds)->toContain($createdId);

    $updatePayload = [
        'id' => $createdId,
        'name' => 'Updated Brand',
        'description' => 'Updated description',
        'cvr' => 43423010,
        'address' => 'Updatedvej 1, 1000 Kobenhavn',
        'phone_country_code' => 46,
        'phone' => 87654321,
        'email' => 'updated@example.test',
        'website' => 'https://updated.example.test',
        'banner' => 'https://cdn.example.test/updated-banner.png',
        'logo' => 'https://cdn.example.test/updated-logo.png',
        'favicon' => 'https://cdn.example.test/updated-favicon.ico',
        'signature' => '',
    ];

    $updateResponse = api_client()->put('/branding', $updatePayload, $session['headers']);

    $updateResponse
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();

    $updatedRow = api_fixtures()->fetchRowById('branding', $createdId);
    expect($updatedRow)->not->toBeNull();
    expect($updatedRow['name'] ?? null)->toBe('Updated Brand');
    expect((int)($updatedRow['cvr'] ?? 0))->toBe(43423010);
    expect($updatedRow['logo'] ?? null)->toBe('https://cdn.example.test/updated-logo.png');
    expect(array_key_exists('signature', $updatedRow))->toBeTrue();
    expect($updatedRow['signature'])->toBeNull();
});

it('rejects branding requests without permissions or valid input', function (): void {
    api_test_covers('GET /branding', 'auth');
    api_test_covers('POST /branding', 'failure');
    api_test_covers('PUT /branding', 'failure');

    $unauthorizedSession = api_fixtures()->createUserSession([]);

    api_client()->get('/branding', $unauthorizedSession['headers'])
        ->assertStatus(403)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMissingPermissions(['list_branding_options']);

    $createSession = api_fixtures()->createUserSession(['add_branding_option']);

    api_client()->post('/branding', [
        'name' => 'Invalid Brand',
        'description' => 'Missing CVR',
    ], $createSession['headers'])
        ->assertStatus(400)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMessage('Missing required parameters: cvr');

    api_client()->post('/branding', [
        'name' => 'Invalid Brand',
        'description' => 'Bad CVR',
        'cvr' => 'not-a-number',
    ], $createSession['headers'])
        ->assertStatus(400)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMessage('cvr must be an integer');

    $editSession = api_fixtures()->createUserSession(['edit_branding_option']);

    api_client()->put('/branding', [
        'id' => 99999999,
        'name' => 'Missing Brand',
    ], $editSession['headers'])
        ->assertStatus(400)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMessage('Invalid id');
});

it('assigns and clears department branding for superusers', function (): void {
    api_test_covers('PUT /superuser/department/branding', 'happy');

    $branding = api_fixtures()->createBranding([
        'name' => 'Assignable Brand',
        'description' => 'Brand for assignment',
    ]);
    $department = api_fixtures()->createDepartment([
        'name' => 'Branding Department',
    ]);
    $session = api_fixtures()->createUserSession([
        'superuser_set_department_branding',
        'superuser_fetch_department',
    ]);

    $assignResponse = api_client()->put('/superuser/department/branding', [
        'department_id' => $department['id'],
        'branding_id' => $branding['id'],
    ], $session['headers']);

    $assignResponse
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();

    $assignedRow = api_fixtures()->fetchRowById('departments', (int)$department['id']);
    expect((int)($assignedRow['branding'] ?? 0))->toBe((int)$branding['id']);

    $departmentResponse = api_client()->get('/superuser/department?department_id=' . $department['id'], $session['headers']);

    $departmentResponse
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();
    expect((int)($departmentResponse->data()['branding'] ?? 0))->toBe((int)$branding['id']);

    $clearResponse = api_client()->put('/superuser/department/branding', [
        'department_id' => $department['id'],
        'branding_id' => null,
    ], $session['headers']);

    $clearResponse
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();

    $clearedRow = api_fixtures()->fetchRowById('departments', (int)$department['id']);
    expect(array_key_exists('branding', $clearedRow))->toBeTrue();
    expect($clearedRow['branding'])->toBeNull();
});

it('rejects invalid department branding assignments', function (): void {
    api_test_covers('PUT /superuser/department/branding', 'failure');

    $department = api_fixtures()->createDepartment();
    $unauthorizedSession = api_fixtures()->createUserSession([]);

    api_client()->put('/superuser/department/branding', [
        'department_id' => $department['id'],
        'branding_id' => null,
    ], $unauthorizedSession['headers'])
        ->assertStatus(403)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMissingPermissions(['superuser_set_department_branding']);

    $session = api_fixtures()->createUserSession(['superuser_set_department_branding']);

    api_client()->put('/superuser/department/branding', [
        'department_id' => $department['id'],
        'branding_id' => 99999999,
    ], $session['headers'])
        ->assertStatus(404)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMessage('Branding not found');

    api_client()->put('/superuser/department/branding', [
        'department_id' => 99999999,
        'branding_id' => null,
    ], $session['headers'])
        ->assertStatus(404)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMessage('Department not found');
});
