# SPDX-FileCopyrightText: UL Research Institutes
# SPDX-License-Identifier: Apache-2.0

import io

import pytest
import ruamel.yaml
from ruamel.yaml.scalarstring import FoldedScalarString

from cici.providers.gitlab.yaml_style import make_scalar_string


# test the folding when handling string literals
@pytest.mark.parametrize(
    "command_text",
    [
        # long command with pipe
        "toolA subcommand with many flags and arguments that make this command exceed "
        "a typical width threshold | toolB --option value --another-option something",
        # long command with multiple pipes
        "cmd1 --foo bar --baz qux | cmd2 --long-option here | cmd3 --final-stage",
        # long command without pipe
        "someverylongcommandname with a lot of arguments and flags that keeps going "
        "and going and going until it is clearly longer than any sane line width",
        # command with && and ;
        "step1 --flag value && step2 --another value ; step3 --final",
    ],
    ids=[
        "long-command-with-pipe",
        "long-command-with-multiple-pipes",
        "long-command-no-pipe",
        "long-command-with-operators",
    ],
)
def test_styled_command_has_no_semantic_newlines(command_text):
    styled = make_scalar_string(command_text)

    # If folding is used, it must be display-only
    if isinstance(styled, FoldedScalarString):
        assert "\n" not in str(styled), (
            "FoldedScalarString must not contain real newlines; "
            "folding must be display-only"
        )


# make sure ruamel dumping never prints the blank line
@pytest.mark.parametrize(
    "command_text",
    [
        "toolA subcommand with many flags and arguments that make this command exceed "
        "a typical width threshold | toolB --option value --another-option something",
        "cmd1 --foo bar --baz qux | cmd2 --long-option here | cmd3 --final-stage",
        "someverylongcommandname with a lot of arguments and flags that keeps going "
        "and going and going until it is clearly longer than any sane line width",
    ],
    ids=[
        "yaml-dump-no-blank-line-case1",
        "yaml-dump-no-blank-line-case2",
        "yaml-dump-no-blank-line-case3",
    ],
)
def test_yaml_dump_has_no_blank_line_in_folded_scalar(command_text):
    styled = make_scalar_string(command_text)

    data = {
        "job": {
            "script": [styled, "echo ok"],
        }
    }

    yaml = ruamel.yaml.YAML(typ="rt")
    yaml.width = 120
    yaml.indent(mapping=2, sequence=4, offset=2)
    yaml.default_flow_style = False

    out = io.StringIO()
    yaml.dump(data, out)
    emitted = out.getvalue()

    lines = emitted.splitlines()

    # Find folded scalar start
    try:
        folded_start = next(
            i for i, line in enumerate(lines) if line.strip() in ("- >-", "- >")
        )
    except StopIteration:
        pytest.skip("No folded scalar emitted; nothing to assert")

    # Inspect a small window of the folded block
    folded_block = lines[folded_start : folded_start + 8]

    # Regression guard: no visually empty line inside folded scalar
    assert not any(line.strip() == "" for line in folded_block[1:]), "\n".join(
        folded_block
    )


@pytest.mark.parametrize(
    "command",
    [
        # generic echo | docker login case
        'echo "password" | docker login "registry" -u "user" --password-stdin',
        # generic long piped command
        'echo "token" | some-tool login --flag-a --flag-b --flag-c --flag-d',
        # generic curl | tar example
        "curl https://example.com/archive.tar.gz | tar -C /usr/local/bin -xzf -",
    ],
    ids=[
        "echo-pipe-docker-login",
        "echo-pipe-generic-tool",
        "curl-pipe-tar",
    ],
)
def test_folded_scalar_does_not_insert_blank_lines(command):
    """
    Folded scalars should:
    - contain no semantic newlines
    - fold visually using >-
    - not introduce blank lines in YAML output
    """

    scalar = make_scalar_string(command)

    # 1. Value must not contain semantic newlines
    assert isinstance(scalar, FoldedScalarString)
    assert "\n" not in str(scalar)

    # 2. Dump YAML
    yaml = ruamel.yaml.YAML()
    yaml.width = 120

    data = {"script": [scalar]}
    stream = io.StringIO()
    yaml.dump(data, stream)
    output = stream.getvalue()

    # 3. Must be folded
    assert ">-" in output

    # 4. Must not contain blank line inside folded block
    # (blank line would show up as double newline)
    assert "\n\n" not in output

    # 5. The command must still appear intact
    for part in command.split():
        assert part in output
