"""Unit tests for cloud_init.py — NoCloud ISO generation."""

from __future__ import annotations

import os
from unittest.mock import MagicMock, patch

import pytest


def test_generate_cloud_init_iso_creates_iso(tmp_path):
    """generate_cloud_init_iso returns an ISO file path in the output dir."""
    from vmcluster_mcp.cluster.cloud_init import generate_cloud_init_iso

    with patch("vmcluster_mcp.cluster.cloud_init.subprocess.run") as mock_run:
        mock_run.return_value = MagicMock(returncode=0)
        iso_path = generate_cloud_init_iso(
            cluster_name="mycluster",
            node_name="node1",
            ip="192.168.100.10",
            mac_address="52:54:00:ab:cd:ef",
            gateway_ip="192.168.100.1",
            prefix_len=24,
            output_dir=str(tmp_path),
        )
    assert iso_path == str(tmp_path / "node1-cidata.iso")


def test_generate_cloud_init_iso_calls_genisoimage(tmp_path):
    """generate_cloud_init_iso calls genisoimage subprocess."""
    from vmcluster_mcp.cluster.cloud_init import generate_cloud_init_iso

    with patch("vmcluster_mcp.cluster.cloud_init.subprocess.run") as mock_run:
        mock_run.return_value = MagicMock(returncode=0)
        generate_cloud_init_iso("mycluster", "node1", "192.168.100.10", "52:54:00:ab:cd:ef", "192.168.100.1", 24, str(tmp_path))
        assert mock_run.called
        cmd = mock_run.call_args[0][0]
        assert cmd[0] in ("genisoimage", "mkisofs")
        assert "cidata" in cmd
        assert "meta-data" in cmd
        assert "network-config" in cmd


def test_generate_cloud_init_iso_meta_data_contents(tmp_path):
    """generate_cloud_init_iso writes correct instance-id and local-hostname."""
    from vmcluster_mcp.cluster.cloud_init import generate_cloud_init_iso

    written_files = {}

    def fake_run(cmd, cwd=None, capture_output=False, check=False):
        # Capture the meta-data content by reading from cwd
        meta_path = os.path.join(cwd, "meta-data")
        net_path = os.path.join(cwd, "network-config")
        if os.path.exists(meta_path):
            written_files["meta-data"] = open(meta_path).read()
        if os.path.exists(net_path):
            written_files["network-config"] = open(net_path).read()
        return MagicMock(returncode=0)

    with patch("vmcluster_mcp.cluster.cloud_init.subprocess.run", side_effect=fake_run):
        generate_cloud_init_iso("mycluster", "node1", "192.168.100.10", "52:54:00:ab:cd:ef", "192.168.100.1", 24, str(tmp_path))

    assert "meta-data" in written_files
    assert "instance-id: mycluster-node1" in written_files["meta-data"]
    assert "local-hostname: node1" in written_files["meta-data"]


def test_generate_cloud_init_iso_network_config_contents(tmp_path):
    """generate_cloud_init_iso writes v2 network-config with MAC match and static IP."""
    from vmcluster_mcp.cluster.cloud_init import generate_cloud_init_iso

    written_files = {}

    def fake_run(cmd, cwd=None, capture_output=False, check=False):
        net_path = os.path.join(cwd, "network-config")
        if os.path.exists(net_path):
            written_files["network-config"] = open(net_path).read()
        return MagicMock(returncode=0)

    with patch("vmcluster_mcp.cluster.cloud_init.subprocess.run", side_effect=fake_run):
        generate_cloud_init_iso("mycluster", "node1", "192.168.100.10", "52:54:00:ab:cd:ef", "192.168.100.1", 24, str(tmp_path))

    assert "network-config" in written_files
    nc = written_files["network-config"]
    assert "version: 2" in nc
    assert "52:54:00:ab:cd:ef" in nc
    assert "192.168.100.10/24" in nc
    assert "192.168.100.1" in nc  # gateway


def test_generate_cloud_init_iso_mkisofs_fallback(tmp_path):
    """generate_cloud_init_iso falls back to mkisofs if genisoimage not found."""
    from vmcluster_mcp.cluster.cloud_init import generate_cloud_init_iso

    call_count = [0]

    def fake_run(cmd, cwd=None, capture_output=False, check=False):
        call_count[0] += 1
        if cmd[0] == "genisoimage":
            raise FileNotFoundError("genisoimage not found")
        return MagicMock(returncode=0)

    with patch("vmcluster_mcp.cluster.cloud_init.subprocess.run", side_effect=fake_run):
        generate_cloud_init_iso("mycluster", "node1", "192.168.100.10", "52:54:00:ab:cd:ef", "192.168.100.1", 24, str(tmp_path))

    assert call_count[0] == 2  # first genisoimage attempt, then mkisofs
