<?php

use App\Services\ContentSanitizer;

// ── Rendering ─────────────────────────────────────────────────────────────────

test('render converts bold markdown to strong tag', function () {
    $html = ContentSanitizer::render('**bold text**');
    expect($html)->toContain('<strong>bold text</strong>');
});

test('render converts italic markdown to em tag', function () {
    $html = ContentSanitizer::render('*italic text*');
    expect($html)->toContain('<em>italic text</em>');
});

test('render converts inline code to code tag', function () {
    $html = ContentSanitizer::render('use `code`');
    expect($html)->toContain('<code>code</code>');
});

test('render auto-links URLs', function () {
    $html = ContentSanitizer::render('visit https://example.com for more');
    expect($html)->toContain('<a');
    expect($html)->toContain('href="https://example.com"');
});

test('render returns empty string for null input', function () {
    expect(ContentSanitizer::render(null))->toBe('');
});

test('render returns empty string for whitespace-only input', function () {
    expect(ContentSanitizer::render('   '))->toBe('');
});

test('render preserves emoji characters in output', function () {
    $html = ContentSanitizer::render('Love this piece 🚀🔥');

    expect($html)->toContain('🚀')
        ->and($html)->toContain('🔥');
});

// ── XSS Prevention ────────────────────────────────────────────────────────────

test('render strips script tags', function () {
    $html = ContentSanitizer::render('<script>alert("xss")</script>hello');
    // The <script> tag itself must be gone (cannot execute)
    expect($html)->not()->toContain('<script>');
    // The word "hello" after the script block should appear
    expect($html)->toContain('hello');
    // Text inside script is rendered as harmless plain text — acceptable
    // Critical: no executable script element exists in the output
});

test('render strips iframe tags', function () {
    $html = ContentSanitizer::render('<iframe src="evil.com"></iframe>');
    expect($html)->not()->toContain('<iframe');
});

test('render strips javascript: links', function () {
    $html = ContentSanitizer::render('[click me](javascript:alert(1))');
    expect($html)->not()->toContain('javascript:');
});

test('render strips style attributes', function () {
    $html = ContentSanitizer::render('<b style="color:red">red</b>');
    expect($html)->not()->toContain('style=');
});

test('render strips onclick attributes', function () {
    $html = ContentSanitizer::render('<b onclick="evil()">text</b>');
    expect($html)->not()->toContain('onclick');
});

test('render adds rel=noopener to external links', function () {
    $html = ContentSanitizer::render('[link](https://example.com)');
    expect($html)->toContain('rel="noopener noreferrer nofollow"');
});

test('sanitizeRenderedHtml keeps allowed formatting tags', function () {
    $html = ContentSanitizer::sanitizeRenderedHtml('<p><strong>Bold</strong> and <em>italic</em> with <a href="/categories">link</a></p>');

    expect($html)
        ->toContain('<p>')
        ->toContain('<strong>Bold</strong>')
        ->toContain('<em>italic</em>')
        ->toContain('<a href="/categories"')
        ->toContain('rel="noopener noreferrer nofollow"');
});

test('sanitizeRenderedHtml strips script tags and event handlers', function () {
    $html = ContentSanitizer::sanitizeRenderedHtml('<p onclick="evil()">Hello<script>alert(1)</script></p>');

    expect($html)
        ->not()->toContain('<script')
        ->not()->toContain('onclick')
        ->toContain('Hello');
});

test('sanitizeRenderedHtml strips javascript links', function () {
    $html = ContentSanitizer::sanitizeRenderedHtml('<a href="javascript:alert(1)">click</a>');

    expect($html)
        ->not()->toContain('javascript:')
        ->toContain('click');
});

// ── Legacy HTML conversion ────────────────────────────────────────────────────

test('render converts legacy bold HTML to markdown output', function () {
    $html = ContentSanitizer::render('<b>old bold</b>');
    expect($html)->toContain('<strong>');
    expect($html)->not()->toContain('<script>');
});

test('render converts br tags to line breaks', function () {
    $html = ContentSanitizer::render("line one<br>line two");
    // Should not contain the raw <br> tag in unexpected ways
    expect($html)->toContain('line one');
    expect($html)->toContain('line two');
});

// ── Plain text ────────────────────────────────────────────────────────────────

test('stripToPlain removes all HTML', function () {
    $plain = ContentSanitizer::stripToPlain('<p>Hello <b>world</b>!</p>');
    expect($plain)->toBe('Hello world!');
});

test('stripToPlain converts br to newline', function () {
    $plain = ContentSanitizer::stripToPlain("line one<br>line two");
    expect($plain)->toContain("\n");
});

// ── Validation ────────────────────────────────────────────────────────────────

test('validate returns error for raw HTML tags', function () {
    $errors = ContentSanitizer::validate('<script>evil</script>');
    expect($errors)->not()->toBeEmpty();
    expect(implode(' ', $errors))->toContain('HTML');
});

test('validate passes for clean markdown', function () {
    $errors = ContentSanitizer::validate('**bold** and *italic* and `code`');
    expect($errors)->toBeEmpty();
});

test('validate returns error when content is too long', function () {
    $errors = ContentSanitizer::validate(str_repeat('a', 10_001));
    expect($errors)->not()->toBeEmpty();
});

test('validate returns error when emoji density exceeds threshold', function () {
    // 10 fire emoji + 4 spaces = 14 chars; emoji count = 10; density = 10/14 ≈ 0.71 > 0.40
    $floodContent = implode(' ', array_fill(0, 10, '🔥'));
    $errors = ContentSanitizer::validate($floodContent);
    expect($errors)->not()->toBeEmpty();
    expect(implode(' ', $errors))->toContain('emoji');
});

test('validate accepts content with reasonable emoji usage', function () {
    // 3 emoji in a 50-char string — density ≈ 0.06, well below threshold
    $errors = ContentSanitizer::validate('Great work on this piece 🎨 love the colours ❤️ keep it up 👏');
    expect($errors)->toBeEmpty();
});

// ── collapseFlood ─────────────────────────────────────────────────────────────

test('collapseFlood delegates to LegacySmileyMapper and collapses runs', function () {
    $input  = implode(' ', array_fill(0, 8, '🍺'));
    $result = ContentSanitizer::collapseFlood($input);
    expect($result)->toContain('×8');
    expect(substr_count($result, '🍺'))->toBeLessThanOrEqual(5);
});

test('collapseFlood returns unchanged string when no flood present', function () {
    $input = 'Nice art 🎨 love it ❤️';
    expect(ContentSanitizer::collapseFlood($input))->toBe($input);
});
