#!/usr/bin/python3
"""Tests for slpkg.views.package_info.InfoPackage pure data methods."""

import json

import pytest

from slpkg.views.package_info import InfoPackage


def make_info_package(option_for_pkg_version: bool = False, option_json: bool = False) -> InfoPackage:
    """Construct InfoPackage bypassing __init__ (avoids Repositories/config_load)."""
    ip: InfoPackage = object.__new__(InfoPackage)
    ip.option_for_pkg_version = option_for_pkg_version
    ip.option_json = option_json
    ip._json_records = []
    ip.homepage = ""
    ip.maintainer = ""
    ip.email = ""
    ip.dependencies = ""
    ip.info_file = []
    ip.repository_packages = ()
    ip.repository = "sbo"
    ip.readme = []
    ip.repo_build_tag = "N/A"
    ip.mirror = ""
    ip.repo_tar_suffix = ""
    return ip


# ---------------------------------------------------------------------------
# assign_the_info_file_variables()
# Parses self.info_file list for HOMEPAGE, MAINTAINER, EMAIL lines.
# Format: HOMEPAGE="value"\n  →  line[10:-2].strip()
#         MAINTAINER="value"\n →  line[12:-2].strip()
#         EMAIL="value"\n      →  line[7:-2].strip()
# ---------------------------------------------------------------------------


def test_assign_homepage() -> None:
    ip = make_info_package()
    ip.info_file = ['HOMEPAGE="https://ffmpeg.org/"\n']
    ip.assign_the_info_file_variables()
    assert ip.homepage == "https://ffmpeg.org/"


def test_assign_maintainer() -> None:
    ip = make_info_package()
    ip.info_file = ['MAINTAINER="John Doe"\n']
    ip.assign_the_info_file_variables()
    assert ip.maintainer == "John Doe"


def test_assign_email() -> None:
    ip = make_info_package()
    ip.info_file = ['EMAIL="john@example.com"\n']
    ip.assign_the_info_file_variables()
    assert ip.email == "john@example.com"


def test_assign_all_three_fields() -> None:
    ip = make_info_package()
    ip.info_file = [
        'HOMEPAGE="https://example.org/"\n',
        'MAINTAINER="Jane Smith"\n',
        'EMAIL="jane@example.org"\n',
    ]
    ip.assign_the_info_file_variables()
    assert ip.homepage == "https://example.org/"
    assert ip.maintainer == "Jane Smith"
    assert ip.email == "jane@example.org"


def test_assign_empty_info_file_leaves_defaults() -> None:
    ip = make_info_package()
    ip.info_file = []
    ip.assign_the_info_file_variables()
    assert ip.homepage == ""
    assert ip.maintainer == ""
    assert ip.email == ""


def test_assign_unrelated_lines_ignored() -> None:
    ip = make_info_package()
    ip.info_file = [
        'PRGNAM="ffmpeg"\n',
        'VERSION="7.1"\n',
        'HOMEPAGE="https://ffmpeg.org/"\n',
    ]
    ip.assign_the_info_file_variables()
    assert ip.homepage == "https://ffmpeg.org/"
    assert ip.maintainer == ""
    assert ip.email == ""


def test_assign_resets_previous_values() -> None:
    """assign_the_info_file_variables always resets fields before parsing."""
    ip = make_info_package()
    ip.homepage = "old_value"
    ip.maintainer = "old_maintainer"
    ip.info_file = []
    ip.assign_the_info_file_variables()
    assert ip.homepage == ""
    assert ip.maintainer == ""


# ---------------------------------------------------------------------------
# assign_dependencies()
# requires is list → ', '.join(requires)
# requires is not list → 'N/A'
# ---------------------------------------------------------------------------


def test_assign_dependencies_list_joined() -> None:
    ip = make_info_package()
    ip.assign_dependencies({"requires": ["libvpx", "x264", "yasm"]})
    assert ip.dependencies == "libvpx, x264, yasm"


def test_assign_dependencies_empty_list() -> None:
    ip = make_info_package()
    ip.assign_dependencies({"requires": []})
    assert ip.dependencies == ""


def test_assign_dependencies_single_item() -> None:
    ip = make_info_package()
    ip.assign_dependencies({"requires": ["yasm"]})
    assert ip.dependencies == "yasm"


def test_assign_dependencies_missing_key_defaults_empty() -> None:
    ip = make_info_package()
    ip.assign_dependencies({})  # no 'requires' key → item.get('requires', []) = []
    assert ip.dependencies == ""


def test_assign_dependencies_not_list_gives_na() -> None:
    ip = make_info_package()
    ip.assign_dependencies({"requires": "yasm"})  # string, not list
    assert ip.dependencies == "N/A"


# ---------------------------------------------------------------------------
# assign_dependencies_with_version()
# Only runs when option_for_pkg_version=True.
# Packages found in both data and repository_packages → "pkg-version"
# Packages not found → plain "pkg"
# ---------------------------------------------------------------------------


def test_assign_deps_with_version_option_off_no_change(sample_data: dict) -> None:
    ip = make_info_package(option_for_pkg_version=False)
    ip.dependencies = "original"
    ip.assign_dependencies_with_version({"requires": ["yasm"]}, sample_data)
    # option is off → no change
    assert ip.dependencies == "original"


def test_assign_deps_with_version_known_packages(sample_data: dict) -> None:
    ip = make_info_package(option_for_pkg_version=True)
    ip.repository_packages = tuple(sample_data.keys())
    ip.assign_dependencies_with_version({"requires": ["yasm", "bash"]}, sample_data)
    assert "yasm-1.3.0" in ip.dependencies
    assert "bash-5.2.026" in ip.dependencies


def test_assign_deps_with_version_unknown_package_no_version(sample_data: dict) -> None:
    ip = make_info_package(option_for_pkg_version=True)
    ip.repository_packages = tuple(sample_data.keys())
    ip.assign_dependencies_with_version({"requires": ["ghost"]}, sample_data)
    # ghost not in data → plain 'ghost'
    assert ip.dependencies == "ghost"


def test_assign_deps_with_version_mixed(sample_data: dict) -> None:
    ip = make_info_package(option_for_pkg_version=True)
    ip.repository_packages = tuple(sample_data.keys())
    ip.assign_dependencies_with_version({"requires": ["yasm", "ghost"]}, sample_data)
    assert "yasm-1.3.0" in ip.dependencies
    assert "ghost" in ip.dependencies


def test_assign_deps_with_version_empty_requires(sample_data: dict) -> None:
    ip = make_info_package(option_for_pkg_version=True)
    ip.repository_packages = tuple(sample_data.keys())
    ip.assign_dependencies_with_version({"requires": []}, sample_data)
    assert ip.dependencies == ""


def test_assign_deps_with_version_not_list_gives_na(sample_data: dict) -> None:
    ip = make_info_package(option_for_pkg_version=True)
    ip.repository_packages = tuple(sample_data.keys())
    ip.assign_dependencies_with_version({"requires": "yasm"}, sample_data)
    assert ip.dependencies == "N/A"


# ---------------------------------------------------------------------------
# view_slackbuild_package() / view_binary_package() — --json accumulation
# ---------------------------------------------------------------------------

_SBO_ITEM: dict = {
    "version": "7.1",
    "build": "1",
    "location": "multimedia",
    "description": "A complete, cross-platform solution.",
    "download": ["https://example.org/ffmpeg-7.1.tar.gz"],
    "md5sum": ["abc123"],
    "download64": [],
    "md5sum64": [],
    "files": ["ffmpeg.SlackBuild"],
    "requires": ["yasm", "x264"],
}

_BIN_ITEM: dict = {
    "version": "7.1",
    "build": "1",
    "package": "ffmpeg-7.1-x86_64-1_alien.txz",
    "mirror": "https://example.org/",
    "location": "/pub/pkgs/",
    "checksum": "deadbeef",
    "size_comp": "12345",
    "size_uncomp": "45678",
    "conflicts": "N/A",
    "suggests": "N/A",
    "description": "FFmpeg binary package.",
}


def test_view_slackbuild_package_json_accumulates_record(capsys: pytest.CaptureFixture) -> None:
    ip = make_info_package(option_json=True)
    ip.view_slackbuild_package("ffmpeg", _SBO_ITEM)
    assert len(ip._json_records) == 1
    assert capsys.readouterr().out == ""  # no print yet — caller prints after loop


def test_view_slackbuild_package_json_record_keys(capsys: pytest.CaptureFixture) -> None:
    ip = make_info_package(option_json=True)
    ip.view_slackbuild_package("ffmpeg", _SBO_ITEM)
    record = ip._json_records[0]
    for key in ("repository", "name", "version", "build", "homepage", "sbo_url",
                 "sources", "md5sum", "category", "maintainer", "email",
                 "requires", "description", "readme"):
        assert key in record, f"Missing key: {key}"


def test_view_slackbuild_package_json_name_correct(capsys: pytest.CaptureFixture) -> None:
    ip = make_info_package(option_json=True)
    ip.view_slackbuild_package("ffmpeg", _SBO_ITEM)
    assert ip._json_records[0]["name"] == "ffmpeg"


def test_view_slackbuild_package_json_multiple_packages_accumulate(capsys: pytest.CaptureFixture) -> None:
    ip = make_info_package(option_json=True)
    ip.view_slackbuild_package("ffmpeg", _SBO_ITEM)
    ip.view_slackbuild_package("vlc", _SBO_ITEM)
    assert len(ip._json_records) == 2
    assert ip._json_records[1]["name"] == "vlc"


def test_view_slackbuild_package_text_mode_prints_output(capsys: pytest.CaptureFixture) -> None:
    ip = make_info_package(option_json=False)
    ip.view_slackbuild_package("ffmpeg", _SBO_ITEM)
    out = capsys.readouterr().out
    assert "ffmpeg" in out
    assert "7.1" in out


def test_view_binary_package_json_accumulates_record(capsys: pytest.CaptureFixture) -> None:
    ip = make_info_package(option_json=True)
    ip.view_binary_package("ffmpeg", _BIN_ITEM)
    assert len(ip._json_records) == 1
    assert capsys.readouterr().out == ""  # no print yet — caller prints after loop


def test_view_binary_package_json_record_keys(capsys: pytest.CaptureFixture) -> None:
    ip = make_info_package(option_json=True)
    ip.view_binary_package("ffmpeg", _BIN_ITEM)
    record = ip._json_records[0]
    for key in ("repository", "name", "version", "build", "package", "download",
                 "md5sum", "mirror", "location", "size_comp_kb", "size_uncomp_kb",
                 "requires", "conflicts", "suggests", "description"):
        assert key in record, f"Missing key: {key}"


def test_view_binary_package_json_name_correct(capsys: pytest.CaptureFixture) -> None:
    ip = make_info_package(option_json=True)
    ip.view_binary_package("ffmpeg", _BIN_ITEM)
    assert ip._json_records[0]["name"] == "ffmpeg"


def test_view_binary_package_text_mode_prints_output(capsys: pytest.CaptureFixture) -> None:
    ip = make_info_package(option_json=False)
    ip.view_binary_package("ffmpeg", _BIN_ITEM)
    out = capsys.readouterr().out
    assert "ffmpeg" in out
    assert "7.1" in out
