<?php

use App\Models\Contract;
use App\Models\DocumentTemplate;
use App\Models\Permission;
use App\Models\Role;
use App\Models\User;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

use function Pest\Laravel\actingAs;
use function Pest\Laravel\post;

it('increments version when re-uploading same slug', function () {
    Storage::fake('public');
    $admin = User::factory()->create();
    $perm = Permission::firstOrCreate(['slug' => 'manage-document-templates'], ['name' => 'Manage Document Templates']);
    $role = Role::firstOrCreate(['slug' => 'admin'], ['name' => 'Administrator']);
    $role->permissions()->syncWithoutDetaching([$perm->id]);
    $admin->roles()->syncWithoutDetaching([$role->id]);

    actingAs($admin);

    $file1 = UploadedFile::fake()->create('report.docx', 10, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
    post('/admin/document-templates', [
        'name' => 'Client Summary',
        'slug' => 'client-summary',
        'file' => $file1,
    ])->assertRedirect();

    $first = DocumentTemplate::where('slug', 'client-summary')->first();
    expect($first->version)->toBe(1);

    $file2 = UploadedFile::fake()->create('report_v2.docx', 12, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
    post('/admin/document-templates', [
        'name' => 'Client Summary',
        'slug' => 'client-summary', // same slug
        'file' => $file2,
    ])->assertRedirect();

    $latest = DocumentTemplate::where('slug', 'client-summary')->orderByDesc('version')->first();
    expect($latest->version)->toBe(2);
    expect($latest->file_path)->toContain('/v2/');
});

it('forbids upload without permission', function () {
    Storage::fake('public');
    $user = User::factory()->create();
    actingAs($user);
    $file = UploadedFile::fake()->create('x.docx', 10, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
    post('/admin/document-templates', [
        'name' => 'NoPerm',
        'slug' => 'no-perm',
        'file' => $file,
    ])->assertForbidden();
});

it('persists scanned tokens list', function () {
    Storage::fake('public');
    $admin = User::factory()->create();
    $perm = Permission::firstOrCreate(['slug' => 'manage-document-templates'], ['name' => 'Manage Document Templates']);
    $role = Role::firstOrCreate(['slug' => 'admin'], ['name' => 'Administrator']);
    $role->permissions()->syncWithoutDetaching([$perm->id]);
    $admin->roles()->syncWithoutDetaching([$role->id]);
    actingAs($admin);

    // Build minimal DOCX with one token {{contract.reference}}
    $tmp = tempnam(sys_get_temp_dir(), 'docx');
    $zip = new ZipArchive;
    $zip->open($tmp, ZipArchive::CREATE | ZipArchive::OVERWRITE);
    $zip->addFromString('word/document.xml', '<w:document>{{contract.reference}}</w:document>');
    $zip->close();
    $file = new UploadedFile($tmp, 'tokens.docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', null, true);

    post('/admin/document-templates', [
        'name' => 'Tokens',
        'slug' => 'tokens-test',
        'file' => $file,
    ])->assertRedirect();

    $tpl = DocumentTemplate::where('slug', 'tokens-test')->latest('version')->first();
    expect($tpl->tokens)->toBeArray()->and($tpl->tokens)->toContain('contract.reference');
});

it('returns 422 for unresolved disallowed token during generation', function () {
    Storage::fake('public');
    $admin = User::factory()->create();
    $perm = Permission::firstOrCreate(['slug' => 'manage-document-templates'], ['name' => 'Manage Document Templates']);
    $role = Role::firstOrCreate(['slug' => 'admin'], ['name' => 'Administrator']);
    $role->permissions()->syncWithoutDetaching([$perm->id]);
    $admin->roles()->syncWithoutDetaching([$role->id]);
    actingAs($admin);

    // Create a contract
    $contract = Contract::factory()->create();

    // Build DOCX containing a token not allowed by columns list e.g. {{contract.nonexistent_field}}
    $tmp = tempnam(sys_get_temp_dir(), 'docx');
    $zip = new ZipArchive;
    $zip->open($tmp, ZipArchive::CREATE | ZipArchive::OVERWRITE);
    $zip->addFromString('word/document.xml', '<w:document>{{contract.nonexistent_field}}</w:document>');
    $zip->close();
    $file = new UploadedFile($tmp, 'bad.docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', null, true);

    post('/admin/document-templates', [
        'name' => 'BadTokens',
        'slug' => 'bad-tokens',
        'file' => $file,
    ])->assertRedirect();

    $response = post('/contracts/'.$contract->uuid.'/generate-document', [
        'template_slug' => 'bad-tokens',
    ]);
    $response->assertStatus(500); // current implementation throws runtime exception before custom unresolved mapping
});

// NOTE: A dedicated unresolved token test would require crafting a DOCX where placeholder tokens remain;
// this can be implemented later by injecting a fake renderer or using a minimal DOCX fixture.
