use Test::More;
SKIP: { eval { require Test::Warnings; } or skip($@, 1); }
eval { require 'ddclient'; } or BAIL_OUT($@);

my @test_cases = (
    {
        desc => 'adds a newline',
        args => ['xyz'],
        want => "xyz\n",
    },
    {
        desc => 'removes one trailing newline (before adding a newline)',
        args => ["xyz \n\t\n\n"],
        want => "xyz \n\t\n\n",
    },
    {
        desc => 'accepts msg keyword parameter',
        args => [msg => 'xyz'],
        want => "xyz\n",
    },
    {
        desc => 'msg keyword parameter trumps message parameter',
        args => [msg => 'kw', 'pos'],
        want => "kw\n",
    },
    {
        desc => 'msg keyword parameter trumps message parameter',
        args => [msg => 'kw', 'pos'],
        want => "kw\n",
    },
    {
        desc => 'email appends to email body',
        args => [email => 1, 'foo'],
        init_email => "preexisting message\n",
        want_email => "preexisting message\nfoo\n",
        want => "foo\n",
    },
    {
        desc => 'single-line label',
        args => [label => 'LBL', 'foo'],
        want => "LBL:     > foo\n",
    },
    {
        desc => 'multi-line label',
        args => [label => 'LBL', "foo\nbar"],
        want => ("LBL:     > foo\n" .
                 "LBL:       bar\n"),
    },
    {
        desc => 'single-line long label',
        args => [label => 'VERY LONG LABEL', 'foo'],
        want => "VERY LONG LABEL: > foo\n",
    },
    {
        desc => 'multi-line long label',
        args => [label => 'VERY LONG LABEL', "foo\nbar"],
        want => ("VERY LONG LABEL: > foo\n" .
                 "VERY LONG LABEL:   bar\n"),
    },
    {
        desc => 'single line, no label, single context',
        args => ['foo'],
        ctxs => ['only context'],
        want => "[only context]> foo\n",
    },
    {
        desc => 'single line, no label, two contexts',
        args => ['foo'],
        ctxs => ['context one', 'context two'],
        want => "[context one][context two]> foo\n",
    },
    {
        desc => 'single line, label, two contexts',
        args => [label => 'LBL', 'foo'],
        ctxs => ['context one', 'context two'],
        want => "LBL:     [context one][context two]> foo\n",
    },
    {
        desc => 'multiple lines, label, two contexts',
        args => [label => 'LBL', "foo\nbar"],
        ctxs => ['context one', 'context two'],
        want => ("LBL:     [context one][context two]> foo\n" .
                 "LBL:     [context one][context two]  bar\n"),
    },
    {
        desc => 'string ctx arg',
        args => [label => 'LBL', ctx => 'three', "foo\nbar"],
        ctxs => ['one', 'two'],
        want => ("LBL:     [one][two][three]> foo\n" .
                 "LBL:     [one][two][three]  bar\n"),
    },
    {
        desc => 'arrayref ctx arg',
        args => [label => 'LBL', ctx => ['three', 'four'], "foo\nbar"],
        ctxs => ['one', 'two'],
        want => ("LBL:     [one][two][three][four]> foo\n" .
                 "LBL:     [one][two][three][four]  bar\n"),
    },
    {
        desc => 'undef ctx',
        args => [label => 'LBL', "foo"],
        ctxs => ['one', undef],
        want => "LBL:     [one]> foo\n",
    },
    {
        desc => 'arrayref ctx',
        args => [label => 'LBL', "foo"],
        ctxs => ['one', ['two', 'three']],
        want => "LBL:     [one][two][three]> foo\n",
    },
);

for my $tc (@test_cases) {
    subtest $tc->{desc} => sub {
        $tc->{wantemail} //= '';
        my $output;
        open(my $fh, '>', \$output);
        local $ddclient::emailbody = $tc->{init_email} // '';
        local $ddclient::_l = $ddclient::_l;
        $ddclient::_l = ddclient::pushlogctx($_) for @{$tc->{ctxs} // []};
        {
            local *STDERR = $fh;
            ddclient::logmsg(@{$tc->{args}});
        }
        close($fh);
        is($output, $tc->{want}, 'output text matches');
        is($ddclient::emailbody, $tc->{want_email} // '', 'email content matches');
    }
}

my @logfmt_test_cases = (
    {
        desc => 'single argument is printed directly, not via sprintf',
        args => ['%%'],
        want => "DEBUG:   > %%\n",
    },
    {
        desc => 'multiple arguments are formatted via sprintf',
        args => ['%s', 'foo'],
        want => "DEBUG:   > foo\n",
    },
    {
        desc => 'single argument with context',
        args => [ctx => 'context', '%%'],
        want => "DEBUG:   [context]> %%\n",
    },
    {
        desc => 'multiple arguments with context',
        args => [ctx => 'context', '%s', 'foo'],
        want => "DEBUG:   [context]> foo\n",
    },
);

for my $tc (@logfmt_test_cases) {
    my $got;
    open(my $fh, '>', \$got);
    local $ddclient::globals{debug} = 1;
    %ddclient::globals if 0;
    {
        local *STDERR = $fh;
        ddclient::debug(@{$tc->{args}});
    }
    close($fh);
    is($got, $tc->{want}, $tc->{desc});
}

done_testing();
