import textwrap

import pytest

from debputy.lsp.languages.lsp_debian_copyright import _lint_debian_copyright
from debputy.packages import DctrlParser
from debputy.plugin.api.feature_set import PluginProvidedFeatureSet
from debputy.plugin.api.test_api import build_virtual_file_system
from lint_tests.lint_tutil import (
    group_diagnostics_by_severity,
    LintWrapper,
    diag_range_to_text,
)

from debputy.lsprotocol.types import DiagnosticSeverity


@pytest.fixture
def line_linter(
    debputy_plugin_feature_set: PluginProvidedFeatureSet,
    lint_dctrl_parser: DctrlParser,
) -> LintWrapper:
    return LintWrapper(
        "/nowhere/debian/copyright",
        _lint_debian_copyright,
        debputy_plugin_feature_set,
        lint_dctrl_parser,
    )


def test_dcpy_files_lint(line_linter: LintWrapper) -> None:
    lines = textwrap.dedent(
        """\
    Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/

    Files: foo .//unnecessary///many/slashes
    Copyright: Noone <noone@example.com>
    License: something
     yada yada yada
    """
    ).splitlines(keepends=True)

    diagnostics = line_linter(lines)
    by_severity = group_diagnostics_by_severity(diagnostics)
    assert DiagnosticSeverity.Warning in by_severity

    assert DiagnosticSeverity.Error not in by_severity
    assert DiagnosticSeverity.Hint not in by_severity
    assert DiagnosticSeverity.Information not in by_severity

    warnings = by_severity[DiagnosticSeverity.Warning]
    print(warnings)
    assert len(warnings) == 2

    first_warn, second_warn = warnings

    msg = 'Unnecessary prefix ".//"'
    assert first_warn.message == msg
    assert f"{first_warn.range}" == "2:11-2:14"

    msg = 'Simplify to a single "/"'
    assert second_warn.message == msg
    assert f"{second_warn.range}" == "2:25-2:28"


def test_dcpy_files_matches_dir_lint(line_linter: LintWrapper) -> None:
    lines = textwrap.dedent(
        """\
    Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/

    Files: foo
    Copyright: Noone <noone@example.com>
    License: something
     yada yada yada
    """
    ).splitlines(keepends=True)

    source_root = build_virtual_file_system(["./foo/bar"])
    line_linter.source_root = source_root

    diagnostics = line_linter(lines)
    assert len(diagnostics) == 1
    issue = diagnostics[0]

    msg = "Directories cannot be a match. Use `dir/*` to match everything in it"
    assert issue.message == msg
    assert f"{issue.range}" == "2:7-2:10"
    assert issue.severity == DiagnosticSeverity.Warning


def test_dcpy_anon_real_example_lint(line_linter: LintWrapper) -> None:
    lines = textwrap.dedent(
        """\
    Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
    Source: https://github.com/some-where/some-project
    Upstream-Name: some-project
    Upstream-Contact: https://github.com/some-where/some-project/issues

    Files: *
    Copyright:
     2022-2024 Some One <some-one@example.com>
     2022-2024 some-project contributors
    License: Expat

    Files: debian/*
    Copyright: 2024 Debian Contributor <debian.contributor@example.com>
    License: Expat
    Comment: Debian packaging is licensed under the same terms as upstream

    License: Expat
     Permission is hereby granted, free of charge, to any person obtaining
     a copy of this software and associated documentation files (the
     "Software"), to deal in the Software without restriction, including
     without limitation the rights to use, copy, modify, merge, publish,
     distribute, sublicense, and/or sell copies of the Software, and to
     permit persons to whom the Software is furnished to do so, subject to
     the following conditions:
     .
     The above copyright notice and this permission notice shall be included
     in all copies or substantial portions of the Software.
     .
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    """
    ).splitlines(keepends=True)

    diagnostics = line_linter(lines)
    assert not diagnostics


def test_dcpy_format_https_urls(line_linter: LintWrapper) -> None:
    lines = textwrap.dedent(
        """\
    Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/

    Files: *
    Copyright:
     2022-2024 Some One <some-one@example.com>
     2022-2024 some-project contributors
    License: Expat

    License: Expat
     Permission is hereby granted, free of charge, to any person obtaining
     a copy of this software and associated documentation files (the
     "Software"), to deal in the Software without restriction, including
     without limitation the rights to use, copy, modify, merge, publish,
     distribute, sublicense, and/or sell copies of the Software, and to
     permit persons to whom the Software is furnished to do so, subject to
     the following conditions:
     .
     The above copyright notice and this permission notice shall be included
     in all copies or substantial portions of the Software.
     .
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    """
    ).splitlines(keepends=True)

    diagnostics = line_linter(lines)
    assert diagnostics and len(diagnostics) == 1
    issue = diagnostics[0]

    msg = "The Format URL should use https:// rather than http://"
    assert issue.message == msg
    assert f"{issue.range}" == "0:8-0:15"
    assert issue.severity == DiagnosticSeverity.Warning
    assert diag_range_to_text(lines, issue.range) == "http://"


def test_not_dcpy_syntax_error_before_format(line_linter: LintWrapper) -> None:
    lines = textwrap.dedent(
        """\
    Random error

    Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
    Source: https://github.com/some-where/some-project
    Upstream-Name: some-project
    Upstream-Contact: https://github.com/some-where/some-project/issues
"""
    ).splitlines(keepends=True)

    diagnostics = line_linter(lines)
    assert not diagnostics


def test_not_dcpy_no_format_field(line_linter: LintWrapper) -> None:
    lines = textwrap.dedent(
        """\
    Some free-text debian/copyright file
"""
    ).splitlines(keepends=True)

    diagnostics = line_linter(lines)
    assert not diagnostics
