"""Integration tests with real APT installation in Docker.

These tests verify that packages can be actually installed via apt-get
from repositories created by debrepomanager.
"""

import subprocess
import time
from pathlib import Path

import pytest

pytestmark = pytest.mark.integration


def has_docker() -> bool:
    """Check if Docker is available."""
    try:
        subprocess.run(["docker", "ps"], capture_output=True, check=True, timeout=5)
        return True
    except (
        subprocess.CalledProcessError,
        FileNotFoundError,
        subprocess.TimeoutExpired,
    ):
        return False


def has_aptly() -> bool:
    """Check if aptly is available."""
    try:
        subprocess.run(["aptly", "version"], capture_output=True, check=True, timeout=5)
        return True
    except (
        subprocess.CalledProcessError,
        FileNotFoundError,
        subprocess.TimeoutExpired,
    ):
        return False


def has_fpm() -> bool:
    """Check if fpm is available."""
    try:
        subprocess.run(["fpm", "--version"], capture_output=True, check=True, timeout=5)
        return True
    except (
        subprocess.CalledProcessError,
        FileNotFoundError,
        subprocess.TimeoutExpired,
    ):
        return False


# Skip if required tools not available
pytestmark = [
    pytest.mark.integration,
    pytest.mark.slow,
    pytest.mark.skipif(not has_docker(), reason="Docker not available"),
    pytest.mark.skipif(not has_aptly(), reason="aptly not available"),
    pytest.mark.skipif(not has_fpm(), reason="fpm not available"),
]


@pytest.fixture(scope="module")
def test_repo(tmp_path_factory):
    """Create a complete test repository with packages."""
    from debrepomanager.aptly import AptlyManager
    from debrepomanager.config import Config

    # Setup directories
    config_dir = tmp_path_factory.mktemp("apt_test_config")
    aptly_root = tmp_path_factory.mktemp("apt_test_aptly")
    repo_root = tmp_path_factory.mktemp("apt_test_repo")
    packages_dir = tmp_path_factory.mktemp("apt_test_packages")

    # Get GPG key
    result = subprocess.run(
        ["gpg", "--list-secret-keys", "--keyid-format", "LONG"],
        capture_output=True,
        text=True,
    )
    gpg_key_id = "TEST_KEY"
    for line in result.stdout.split("\n"):
        if "sec" in line:
            parts = line.split()
            if len(parts) > 1 and "/" in parts[1]:
                gpg_key_id = parts[1].split("/")[1]
                break

    # Create config
    config_file = config_dir / "config.yaml"
    config_file.write_text(
        f"""
aptly:
  root_base: {aptly_root}
  publish_base: {repo_root}

gpg:
  key_id: {gpg_key_id}
  use_agent: true

repositories:
  components: [jethome-tools]
  architectures: [amd64]
  auto_create: true
  dual_format:
    enabled: true
    method: symlink
    auto_symlink: true

advanced:
  max_snapshots: 5
"""
    )

    # Create a real test package with postinst script
    codename = "bookworm"
    pkg_name = "jethome-test-app"
    pkg_version = "1.0"

    pkg_tmp = tmp_path_factory.mktemp("pkg_build")
    pkg_content = pkg_tmp / "usr" / "bin"
    pkg_content.mkdir(parents=True)

    # Create a simple script
    script_file = pkg_content / "jethome-test-app"
    script_file.write_text(
        """#!/bin/bash
echo "JetHome Test App v1.0"
echo "Installation successful!"
"""
    )
    script_file.chmod(0o755)

    # Create package
    pkg_output = packages_dir / f"{pkg_name}_{pkg_version}_amd64.deb"
    subprocess.run(
        [
            "fpm",
            "-s",
            "dir",
            "-t",
            "deb",
            "-n",
            pkg_name,
            "-v",
            pkg_version,
            "-a",
            "amd64",
            "--description",
            "Test application for APT integration testing",
            "-C",
            str(pkg_tmp),
            "--package",
            str(pkg_output),
            "usr",
        ],
        check=True,
        capture_output=True,
    )

    # Initialize repo and add package
    config = Config(str(config_file))
    aptly = AptlyManager(config)

    # Create repo
    aptly.create_repo(codename, "jethome-tools", force=True)

    # Add package
    aptly.add_packages(codename, "jethome-tools", [str(pkg_output)])

    # Export GPG public key
    gpg_pub_key = repo_root / "pubkey.gpg"
    subprocess.run(
        ["gpg", "--armor", "--export", gpg_key_id],
        stdout=open(gpg_pub_key, "w"),
        check=True,
    )

    return {
        "repo_root": str(repo_root),
        "config_file": str(config_file),
        "codename": codename,
        "component": "jethome-tools",
        "package_name": pkg_name,
        "gpg_key": str(gpg_pub_key),
    }


@pytest.fixture
def docker_apt_client(test_repo):
    """Start a Docker container with Debian for APT testing."""
    container_name = f"debrepomanager-apt-test-{int(time.time())}"

    # Start container
    subprocess.run(
        [
            "docker",
            "run",
            "-d",
            "--name",
            container_name,
            "-v",
            f"{test_repo['repo_root']}:/repo:ro",
            "debian:bookworm-slim",
            "sleep",
            "3600",
        ],
        check=True,
        capture_output=True,
    )

    yield container_name

    # Cleanup
    subprocess.run(
        ["docker", "rm", "-f", container_name], capture_output=True, check=False
    )


def docker_exec(container_name: str, cmd: list) -> subprocess.CompletedProcess:
    """Execute command in Docker container."""
    return subprocess.run(
        ["docker", "exec", container_name] + cmd,
        capture_output=True,
        text=True,
        timeout=30,
    )


class TestAPTInstallation:
    """Test real APT package installation from created repository."""

    def test_apt_update_with_new_repo(self, docker_apt_client, test_repo):
        """Test that apt update works with our repository."""
        container = docker_apt_client

        # Import GPG key
        result = docker_exec(
            container,
            [
                "bash",
                "-c",
                "apt-get update && apt-get install -y gnupg && "
                "gpg --dearmor < /repo/pubkey.gpg > /etc/apt/trusted.gpg.d/jethome.gpg",
            ],
        )
        assert result.returncode == 0, f"Failed to import GPG key: {result.stderr}"

        # Add repository
        sources_list = (
            f"deb [arch=amd64] file:///repo/{test_repo['codename']} "
            f"{test_repo['component']} main"
        )

        result = docker_exec(
            container,
            [
                "bash",
                "-c",
                f'echo "{sources_list}" > /etc/apt/sources.list.d/jethome.list',
            ],
        )
        assert result.returncode == 0

        # Run apt update
        result = docker_exec(container, ["apt-get", "update"])
        assert result.returncode == 0, f"apt update failed: {result.stderr}"
        assert "jethome" in result.stdout or "jethome" in result.stderr

    def test_apt_install_package(self, docker_apt_client, test_repo):
        """Test installing package via apt-get install."""
        container = docker_apt_client

        # Setup repository (same as test_apt_update_with_new_repo)
        docker_exec(
            container,
            [
                "bash",
                "-c",
                "apt-get update && apt-get install -y gnupg && "
                "gpg --dearmor < /repo/pubkey.gpg > /etc/apt/trusted.gpg.d/jethome.gpg",
            ],
        )

        sources_list = (
            f"deb [arch=amd64] file:///repo/{test_repo['codename']} "
            f"{test_repo['component']} main"
        )
        docker_exec(
            container,
            [
                "bash",
                "-c",
                f'echo "{sources_list}" > /etc/apt/sources.list.d/jethome.list',
            ],
        )

        docker_exec(container, ["apt-get", "update"])

        # Install package
        result = docker_exec(
            container,
            ["apt-get", "install", "-y", test_repo["package_name"]],
        )

        assert result.returncode == 0, f"Package installation failed: {result.stderr}"
        assert test_repo["package_name"] in result.stdout

        # Verify package installed
        result = docker_exec(container, ["dpkg", "-l", test_repo["package_name"]])
        assert result.returncode == 0
        assert test_repo["package_name"] in result.stdout

    def test_package_executable_works(self, docker_apt_client, test_repo):
        """Test that installed package executable works."""
        container = docker_apt_client

        # Setup and install (same as previous test)
        docker_exec(
            container,
            [
                "bash",
                "-c",
                "apt-get update && apt-get install -y gnupg && "
                "gpg --dearmor < /repo/pubkey.gpg > /etc/apt/trusted.gpg.d/jethome.gpg",
            ],
        )

        sources_list = (
            f"deb [arch=amd64] file:///repo/{test_repo['codename']} "
            f"{test_repo['component']} main"
        )
        docker_exec(
            container,
            [
                "bash",
                "-c",
                f'echo "{sources_list}" > /etc/apt/sources.list.d/jethome.list',
            ],
        )

        docker_exec(container, ["apt-get", "update"])
        docker_exec(
            container,
            ["apt-get", "install", "-y", test_repo["package_name"]],
        )

        # Run the installed executable
        result = docker_exec(container, ["jethome-test-app"])

        assert result.returncode == 0, f"Executable failed: {result.stderr}"
        assert "JetHome Test App" in result.stdout
        assert "Installation successful" in result.stdout


class TestEnvironmentAPT:
    """Test APT installation from different environments (stable/beta/test)."""

    def test_stable_beta_isolation(self, tmp_path_factory):
        """Test that stable and beta environments are isolated."""
        import os

        from debrepomanager.aptly import AptlyManager
        from debrepomanager.config import Config
        from debrepomanager.release import ReleaseManager

        # Setup base config
        config_dir = tmp_path_factory.mktemp("env_config")
        aptly_root = tmp_path_factory.mktemp("env_aptly")
        repo_root = tmp_path_factory.mktemp("env_repo")

        # Get GPG key
        result = subprocess.run(
            ["gpg", "--list-secret-keys", "--keyid-format", "LONG"],
            capture_output=True,
            text=True,
        )
        gpg_key_id = "TEST_KEY"
        for line in result.stdout.split("\n"):
            if "sec" in line:
                parts = line.split()
                if len(parts) > 1 and "/" in parts[1]:
                    gpg_key_id = parts[1].split("/")[1]
                    break

        config_file = config_dir / "config.yaml"
        config_file.write_text(
            f"""
aptly:
  root_base: {aptly_root}
  publish_base: {repo_root}

gpg:
  key_id: {gpg_key_id}
  use_agent: true

repositories:
  components: [jethome-tools]
  architectures: [amd64]
  auto_create: true
"""
        )

        # Create release in stable
        os.environ["REPOMANAGER_PUBLISH_PREFIX"] = ""
        config_stable = Config(str(config_file))
        aptly_stable = AptlyManager(config_stable)
        release_stable = ReleaseManager(config_stable, aptly_stable)

        result = release_stable.add_release(
            "testenv", components=["jethome-tools"], skip_symlinks=True
        )
        assert result["created"] == 1

        # Create release in beta
        os.environ["REPOMANAGER_PUBLISH_PREFIX"] = "beta"
        config_beta = Config(str(config_file))
        aptly_beta = AptlyManager(config_beta)
        release_beta = ReleaseManager(config_beta, aptly_beta)

        result = release_beta.add_release(
            "testenv", components=["jethome-tools"], skip_symlinks=True
        )
        assert result["created"] == 1

        # Both should exist independently
        assert aptly_stable.repo_exists("testenv", "jethome-tools")
        assert aptly_beta.repo_exists("testenv", "jethome-tools")

        # Clean up
        del os.environ["REPOMANAGER_PUBLISH_PREFIX"]


class TestReleaseAPTWorkflow:
    """Test complete workflow: release add -> package add -> apt install."""

    @pytest.mark.slow
    def test_complete_workflow(self, tmp_path_factory):
        """Test complete release lifecycle with APT installation."""
        from debrepomanager.aptly import AptlyManager
        from debrepomanager.config import Config
        from debrepomanager.release import ReleaseManager

        # Setup
        config_dir = tmp_path_factory.mktemp("workflow_config")
        aptly_root = tmp_path_factory.mktemp("workflow_aptly")
        repo_root = tmp_path_factory.mktemp("workflow_repo")
        packages_dir = tmp_path_factory.mktemp("workflow_packages")

        # Get GPG key
        result = subprocess.run(
            ["gpg", "--list-secret-keys", "--keyid-format", "LONG"],
            capture_output=True,
            text=True,
        )
        gpg_key_id = "TEST_KEY"
        for line in result.stdout.split("\n"):
            if "sec" in line:
                parts = line.split()
                if len(parts) > 1 and "/" in parts[1]:
                    gpg_key_id = parts[1].split("/")[1]
                    break

        config_file = config_dir / "config.yaml"
        config_file.write_text(
            f"""
aptly:
  root_base: {aptly_root}
  publish_base: {repo_root}

gpg:
  key_id: {gpg_key_id}
  use_agent: true

repositories:
  components: [jethome-workflow]
  architectures: [amd64]
  auto_create: true
"""
        )

        config = Config(str(config_file))
        aptly = AptlyManager(config)
        release_mgr = ReleaseManager(config, aptly)

        # 1. Add release
        result = release_mgr.add_release(
            "workflow", components=["jethome-workflow"], skip_symlinks=True
        )
        assert result["created"] == 1

        # 2. Create and add package
        pkg_tmp = tmp_path_factory.mktemp("workflow_pkg")
        content = pkg_tmp / "usr" / "bin"
        content.mkdir(parents=True)
        (content / "workflow-test").write_text("#!/bin/bash\necho 'Workflow OK'\n")
        (content / "workflow-test").chmod(0o755)

        pkg_file = packages_dir / "workflow-test_1.0_amd64.deb"
        subprocess.run(
            [
                "fpm",
                "-s",
                "dir",
                "-t",
                "deb",
                "-n",
                "workflow-test",
                "-v",
                "1.0",
                "-a",
                "amd64",
                "-C",
                str(pkg_tmp),
                "--package",
                str(pkg_file),
                "usr",
            ],
            check=True,
            capture_output=True,
        )

        aptly.add_packages("workflow", "jethome-workflow", [str(pkg_file)])

        # 3. Verify package in repo
        pkgs = aptly.list_packages("workflow", "jethome-workflow")
        assert len(pkgs) > 0

        # 4. Remove release
        backup_dir = str(tmp_path_factory.mktemp("workflow_backup"))
        result = release_mgr.remove_release(
            "workflow", backup=True, force=True, backup_dir=backup_dir
        )

        assert result["deleted"] == 1
        assert result["backup_file"] is not None
        assert Path(result["backup_file"]).exists()

        # 5. Verify removal
        assert not aptly.repo_exists("workflow", "jethome-workflow")
