<?php

declare(strict_types=1);

namespace Tests\Unit\Lib\Sanitizer;

use Butschster\ContextGenerator\Modifier\Sanitizer\Rule\RegexReplacementRule;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;

class RegexReplacementRuleTest extends TestCase
{
    #[Test]
    public function it_should_return_correct_name(): void
    {
        $rule = new RegexReplacementRule('test-rule', []);
        $this->assertEquals('test-rule', $rule->getName());
    }

    #[Test]
    public function it_should_not_modify_content_with_empty_patterns(): void
    {
        $rule = new RegexReplacementRule('empty-patterns', []);
        $content = "This content should remain unchanged";

        $this->assertEquals($content, $rule->apply($content));
    }

    #[Test]
    public function it_should_apply_single_regex_pattern(): void
    {
        $rule = new RegexReplacementRule(
            name: 'single-pattern',
            patterns: ['/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/' => '[EMAIL_REMOVED]'],
        );

        $content = "Contact us at test@example.com for more information";
        $expected = "Contact us at [EMAIL_REMOVED] for more information";

        $this->assertEquals($expected, $rule->apply($content));
    }

    #[Test]
    public function it_should_apply_multiple_regex_patterns(): void
    {
        $rule = new RegexReplacementRule(
            name: 'multiple-patterns',
            patterns: [
                '/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/' => '[EMAIL_REMOVED]',
                '/\b(?:\d{1,3}\.){3}\d{1,3}\b/' => '[IP_ADDRESS_REMOVED]',
            ],
        );

        $content = "Contact us at test@example.com or visit our server at 192.168.1.1";
        $expected = "Contact us at [EMAIL_REMOVED] or visit our server at [IP_ADDRESS_REMOVED]";

        $this->assertEquals($expected, $rule->apply($content));
    }

    #[Test]
    public function it_should_handle_capture_groups_correctly(): void
    {
        $rule = new RegexReplacementRule(
            name: 'capture-groups',
            patterns: [
                '/password\s*=\s*["\'](.+?)["\']/' => 'password="[REDACTED]"',
            ],
        );

        $content = "config = { password = \"supersecret123\" }";
        $expected = "config = { password=\"[REDACTED]\" }";

        $this->assertEquals($expected, $rule->apply($content));
    }

    #[Test]
    public function it_should_work_with_multiline_content(): void
    {
        $rule = new RegexReplacementRule(
            name: 'multiline',
            patterns: [
                '/\/\*.*?\*\//s' => '[COMMENT_REMOVED]',
            ],
        );

        $content = "function test() {\n  /* This is a\n  multiline comment */\n  return true;\n}";
        $expected = "function test() {\n  [COMMENT_REMOVED]\n  return true;\n}";

        $this->assertEquals($expected, $rule->apply($content));
    }

    #[Test]
    public function it_should_handle_complex_regex_patterns(): void
    {
        $rule = new RegexReplacementRule(
            name: 'complex-patterns',
            patterns: [
                '/\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/' => '[CREDIT_CARD_REMOVED]',
                '/\b(?:\+\d{1,3}[-\s]?)?\(?\d{3}\)?[-\s]?\d{3}[-\s]?\d{4}\b/' => '[PHONE_NUMBER_REMOVED]',
            ],
        );

        $content = "Card: 1234 5678 9012 3456, Phone: (123) 456-7890";
        $expected = "Card: [CREDIT_CARD_REMOVED], Phone: ([PHONE_NUMBER_REMOVED]";

        $this->assertEquals($expected, $rule->apply($content));
    }

    #[Test]
    public function it_should_return_unchanged_content_with_no_matches(): void
    {
        $rule = new RegexReplacementRule(
            name: 'no-matches',
            patterns: [
                '/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/' => '[EMAIL_REMOVED]',
            ],
        );

        $content = "This content has no email addresses";

        $this->assertEquals($content, $rule->apply($content));
    }

    #[Test]
    public function it_should_handle_overlapping_patterns_correctly(): void
    {
        $rule = new RegexReplacementRule(
            name: 'overlapping-patterns',
            patterns: [
                '/secret\d+key/' => '[SECRET_KEY_REMOVED]',
                '/secret\d+code/' => '[SECRET_CODE_REMOVED]',
            ],
        );

        $content = "The code is secret123key and secret456code";
        $expected = "The code is [SECRET_KEY_REMOVED] and [SECRET_CODE_REMOVED]";

        $this->assertEquals($expected, $rule->apply($content));
    }
}
