#!/usr/bin/env perl

use strict;
use warnings;
use Test::More;
use Test::Exception;
use FindBin;
use lib "$FindBin::Bin/../lib";
use Digest::MD5;

# 确保模块可以加载
use_ok('PDK::Config::Context::Static');

# 准备测试数据
my @test_config = (
    "line 1 of config",
    "line 2 of config",
    "",
    "    ", # 只有空格的空行
    "line 5 with special chars: test",
    "line 6 of config"
);

# 测试对象创建
subtest '对象创建' => sub {
    my $config_obj;
    lives_ok {
        $config_obj = PDK::Config::Context::Static->new(
            id     => 1,
            name   => 'test-firewall',
            vendor => 'test',
            config => \@test_config
        );
    } '创建对象应成功';

    isa_ok($config_obj, 'PDK::Config::Context::Static', '对象类型正确');

    # 检查属性
    is_deeply($config_obj->config, \@test_config, 'config属性正确');
    is($config_obj->cursor, 0, 'cursor初始值为0');

    done_testing();
};

# 测试配置签名生成
subtest '配置签名' => sub {
    my $config_obj = PDK::Config::Context::Static->new(
        id     => 1,
        name   => 'test-firewall',
        vendor => 'test',
        config => \@test_config
    );

    # 计算预期的MD5
    my $expected_md5 = Digest::MD5::md5_hex(join("\n", @test_config));
    is($config_obj->confSign, $expected_md5, '配置签名计算正确');

    done_testing();
};

# 测试配置内容生成
subtest '配置内容' => sub {
    my $config_obj = PDK::Config::Context::Static->new(
        id     => 1,
        name   => 'test-firewall',
        vendor => 'test',
        config => \@test_config
    );

    my $expected_content = join("\n", @test_config);
    is($config_obj->confContent, $expected_content, '配置内容正确');

    done_testing();
};

# 测试光标移动
subtest '光标移动' => sub {
    my $config_obj = PDK::Config::Context::Static->new(
        id     => 1,
        name   => 'test-firewall',
        vendor => 'test',
        config => \@test_config
    );

    is($config_obj->cursor, 0, '初始光标位置正确');

    # 测试nextLine
    is($config_obj->nextLine, "line 1 of config", '第一行内容正确');
    is($config_obj->cursor, 1, '光标移动后位置正确');

    # 测试prevLine
    ok($config_obj->prevLine, '移动到上一行成功');
    is($config_obj->cursor, 0, '光标回到位置0');

    # 测试goToHead
    $config_obj->nextLine for 1 .. 3; # 移动光标
    $config_obj->goToHead;
    is($config_obj->cursor, 0, 'goToHead重置光标位置');

    # 测试prevLine边界条件
    $config_obj->goToHead;
    is($config_obj->prevLine, undef, '无法移动到第一行之前');

    done_testing();
};

# 测试解析标志
subtest '解析标志' => sub {
    my $config_obj = PDK::Config::Context::Static->new(
        id     => 1,
        name   => 'test-firewall',
        vendor => 'test',
        config => \@test_config
    );

    # 初始状态所有行都应未解析
    is($config_obj->getParseFlag, 0, '初始解析标志为0');

    # 设置解析标志
    ok($config_obj->setParseFlag(1), '设置解析标志成功');
    is($config_obj->getParseFlag, 1, '解析标志已设置为1');

    # 测试边界条件
    $config_obj->{cursor} = 100; # 超出范围
    is($config_obj->getParseFlag, undef, '超出范围getParseFlag返回undef');
    is($config_obj->setParseFlag(1), undef, '超出范围setParseFlag返回undef');

    done_testing();
};

# 测试未解析行获取
subtest '未解析行获取' => sub {
    my $config_obj = PDK::Config::Context::Static->new(
        id     => 1,
        name   => 'test-firewall',
        vendor => 'test',
        config => \@test_config
    );

    # 获取第一个未解析行（应跳过空行）
    my $line = $config_obj->nextUnParsedLine;
    is($line, "line 1 of config", '第一个未解析行正确');

    # 检查解析标志 - nextUnParsedLine会自动标记为已解析
    # 注意：nextUnParsedLine会移动光标到下一行，所以检查的是下一行的标志
    $config_obj->prevLine; # 回到刚处理的行
    is($config_obj->getParseFlag, 1, '行已标记为已解析');

    # 移动到下一行
    $line = $config_obj->nextUnParsedLine;
    is($line, "line 2 of config", '第二个未解析行正确');

    # 跳过空行
    $line = $config_obj->nextUnParsedLine;
    is($line, "line 5 with special chars: test", '跳过空行后正确获取行');

    # 测试回溯
    $config_obj->backtrack;
    is($config_obj->getParseFlag, 0, '回溯后解析标志重置');

    # 测试ignore
    $config_obj->ignore;
    is($config_obj->cursor, 4, 'ignore后光标位置正确');

    done_testing();
};

# 测试获取所有未解析行
subtest '获取所有未解析行' => sub {
    my $config_obj = PDK::Config::Context::Static->new(
        id     => 1,
        name   => 'test-firewall',
        vendor => 'test',
        config => \@test_config
    );

    # 解析前几行
    $config_obj->nextUnParsedLine for 1 .. 3;

    # 获取未解析行
    my $unparsed = $config_obj->getUnParsedLines;
    like($unparsed, qr/line 6 of config/, '包含未解析行');
    unlike($unparsed, qr/line 1 of config/, '不包含已解析行');

    done_testing();
};

# 测试UTF-8编码
subtest 'UTF-8编码' => sub {
    my @unicode_config = ("line with unicode: test", "another line");
    my $config_obj = PDK::Config::Context::Static->new(
        id     => 1,
        name   => 'test-firewall',
        vendor => 'test',
        config => \@unicode_config
    );

    my $line = $config_obj->nextUnParsedLine;
    is($line, "line with unicode: test", 'UTF-8编码处理正确');

    done_testing();
};

done_testing();
