import os
import tempfile

from xproject_creator.builder import ProjectBuilder


def test_builder_creates_project_structure():
    """Test that the builder creates a valid .xcodeproj bundle."""
    with tempfile.TemporaryDirectory() as tmpdir:
        # Create some dummy Swift files
        src_dir = os.path.join(tmpdir, "MyApp")
        os.makedirs(src_dir)
        with open(os.path.join(src_dir, "MyAppApp.swift"), "w") as f:
            f.write("import SwiftUI\n@main struct MyApp: App {}\n")
        with open(os.path.join(src_dir, "ContentView.swift"), "w") as f:
            f.write("import SwiftUI\nstruct ContentView: View {}\n")

        views_dir = os.path.join(src_dir, "Views")
        os.makedirs(views_dir)
        with open(os.path.join(views_dir, "DetailView.swift"), "w") as f:
            f.write("import SwiftUI\nstruct DetailView: View {}\n")

        # Build the project
        output_path = os.path.join(tmpdir, "MyApp.xcodeproj")

        builder = ProjectBuilder("MyApp", bundle_id="com.example.myapp")
        builder.set_deployment_target("17.0")
        builder.add_swift_sources(src_dir)
        builder.save(output_path)

        # Verify files created
        assert os.path.exists(os.path.join(output_path, "project.pbxproj"))
        assert os.path.exists(
            os.path.join(output_path, "xcshareddata", "xcschemes", "MyApp.xcscheme")
        )

        # Read and verify pbxproj content
        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()

        assert "// !$*UTF8*$!" in content
        assert "PBXSourcesBuildPhase" in content
        assert "PBXNativeTarget" in content
        assert "MyAppApp.swift" in content
        assert "ContentView.swift" in content
        assert "DetailView.swift" in content
        assert "com.example.myapp" in content

        # Verify scheme
        with open(os.path.join(output_path, "xcshareddata", "xcschemes", "MyApp.xcscheme")) as f:
            scheme = f.read()

        assert "MyApp" in scheme
        assert "container:MyApp.xcodeproj" in scheme


def test_builder_fluent_api():
    """Test that fluent methods return self for chaining."""
    builder = ProjectBuilder("Test", bundle_id="com.test.app")
    result = builder.set_deployment_target("18.0").set_swift_version("6.0")
    assert result is builder


def test_builder_asset_catalog():
    """Test adding an asset catalog."""
    with tempfile.TemporaryDirectory() as tmpdir:
        # Create asset catalog directory
        assets_dir = os.path.join(tmpdir, "MyApp", "Assets.xcassets")
        os.makedirs(assets_dir)

        output_path = os.path.join(tmpdir, "MyApp.xcodeproj")

        builder = ProjectBuilder("MyApp", bundle_id="com.example.myapp")
        builder.add_asset_catalog("MyApp/Assets.xcassets")
        builder.save(output_path)

        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()

        assert "Assets.xcassets" in content
        assert "folder.assetcatalog" in content


def test_builder_set_development_team():
    builder = ProjectBuilder("Test", bundle_id="com.test.app")
    result = builder.set_development_team("ABCDEF1234")
    assert result is builder

    with tempfile.TemporaryDirectory() as tmpdir:
        output_path = os.path.join(tmpdir, "Test.xcodeproj")
        builder.save(output_path)
        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()
        assert "ABCDEF1234" in content


def test_builder_set_build_setting_all_configs():
    builder = ProjectBuilder("Test", bundle_id="com.test.app")
    builder.set_build_setting("CUSTOM_FLAG", "YES")

    with tempfile.TemporaryDirectory() as tmpdir:
        output_path = os.path.join(tmpdir, "Test.xcodeproj")
        builder.save(output_path)
        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()
        # Should appear in multiple configs
        assert content.count("CUSTOM_FLAG = YES") >= 2


def test_builder_set_build_setting_specific_config():
    builder = ProjectBuilder("Test", bundle_id="com.test.app")
    builder.set_build_setting("DEBUG_ONLY", "YES", config="Debug")

    with tempfile.TemporaryDirectory() as tmpdir:
        output_path = os.path.join(tmpdir, "Test.xcodeproj")
        builder.save(output_path)
        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()
        # Should appear in Debug configs only (2: project + target level)
        assert content.count("DEBUG_ONLY = YES") == 2
        # Verify all 4 configs exist but only Debug ones got the setting
        assert content.count("CUSTOM_RELEASE_ONLY") == 0


def test_builder_add_resource():
    builder = ProjectBuilder("Test", bundle_id="com.test.app")
    builder.add_resource("Test/data.json")

    with tempfile.TemporaryDirectory() as tmpdir:
        output_path = os.path.join(tmpdir, "Test.xcodeproj")
        builder.save(output_path)
        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()
        assert "data.json" in content
        assert "PBXResourcesBuildPhase" in content


def test_builder_add_resources_glob():
    """Test add_resources with directory glob."""
    with tempfile.TemporaryDirectory() as tmpdir:
        res_dir = os.path.join(tmpdir, "MyApp", "Resources")
        os.makedirs(res_dir)
        with open(os.path.join(res_dir, "data.json"), "w") as f:
            f.write("{}")
        with open(os.path.join(res_dir, "image.png"), "wb") as f:
            f.write(b"\x89PNG")
        # Non-resource file should be skipped
        with open(os.path.join(res_dir, "code.swift"), "w") as f:
            f.write("// swift")

        output_path = os.path.join(tmpdir, "MyApp.xcodeproj")
        builder = ProjectBuilder("MyApp", bundle_id="com.example.myapp")
        builder.add_resources(os.path.join(tmpdir, "MyApp", "Resources"))
        builder.save(output_path)

        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()
        assert "data.json" in content
        assert "image.png" in content
        # Swift file should NOT be in resources
        assert "code.swift" not in content


def test_builder_shell_script_phase():
    builder = ProjectBuilder("Test", bundle_id="com.test.app")
    result = builder.add_shell_script_phase("Lint", "swiftlint")
    assert result is builder

    with tempfile.TemporaryDirectory() as tmpdir:
        output_path = os.path.join(tmpdir, "Test.xcodeproj")
        builder.save(output_path)
        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()
        assert "PBXShellScriptBuildPhase" in content
        assert "swiftlint" in content
        assert "Lint" in content


def test_builder_nested_groups():
    """Test that deeply nested paths create proper group hierarchy."""
    builder = ProjectBuilder("App", bundle_id="com.test.app")
    builder.add_swift_source("App/Views/Settings/SettingsView.swift")

    with tempfile.TemporaryDirectory() as tmpdir:
        output_path = os.path.join(tmpdir, "App.xcodeproj")
        builder.save(output_path)
        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()
        assert "SettingsView.swift" in content
        assert "Settings" in content
        assert "Views" in content


def test_builder_custom_product_type():
    """Test creating a framework instead of an app."""
    builder = ProjectBuilder(
        "MyFramework",
        bundle_id="com.test.framework",
        product_type="com.apple.product-type.framework",
    )

    with tempfile.TemporaryDirectory() as tmpdir:
        output_path = os.path.join(tmpdir, "MyFramework.xcodeproj")
        builder.save(output_path)
        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()
        assert "com.apple.product-type.framework" in content
        assert "MyFramework.framework" in content


def test_builder_v77_creates_file_sync_group():
    """Test that v77 creates PBXFileSystemSynchronizedRootGroup."""
    builder = ProjectBuilder("MyApp", bundle_id="com.test.app", object_version="77")

    with tempfile.TemporaryDirectory() as tmpdir:
        output_path = os.path.join(tmpdir, "MyApp.xcodeproj")
        builder.save(output_path)
        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()

        assert "objectVersion = 77;" in content
        assert "PBXFileSystemSynchronizedRootGroup" in content
        assert "fileSystemSynchronizedGroups" in content
        assert "minimizedProjectReferenceProxies" in content
        assert "preferredProjectObjectVersion" in content
        # v77 should NOT have compatibilityVersion
        assert "compatibilityVersion" not in content


def test_builder_v56_no_file_sync():
    """Test that classic v56 does NOT use file sync groups."""
    builder = ProjectBuilder("MyApp", bundle_id="com.test.app")

    with tempfile.TemporaryDirectory() as tmpdir:
        output_path = os.path.join(tmpdir, "MyApp.xcodeproj")
        builder.save(output_path)
        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()

        assert "objectVersion = 56;" in content
        assert "PBXFileSystemSynchronizedRootGroup" not in content
        assert "fileSystemSynchronizedGroups" not in content
        assert "compatibilityVersion" in content


def test_builder_v77_add_file_sync_group():
    """Test adding an additional file sync group in v77 mode."""
    builder = ProjectBuilder("MyApp", bundle_id="com.test.app", object_version="77")
    result = builder.add_file_sync_group("MyAppTests")
    assert result is builder

    with tempfile.TemporaryDirectory() as tmpdir:
        output_path = os.path.join(tmpdir, "MyApp.xcodeproj")
        builder.save(output_path)
        with open(os.path.join(output_path, "project.pbxproj")) as f:
            content = f.read()

        # Both the default and the added sync group should appear
        assert content.count("PBXFileSystemSynchronizedRootGroup") >= 3  # section + 2 objects
