import json

from django.test import TestCase, override_settings

from ..capabilities import get_capability_registry
from ..services import (
    build_capability_metadata,
    build_capability_statuses,
    build_branding_asset_statuses,
    build_mobile_bridge_script,
    generate_branding_assets,
    get_mobile_bridge_dependencies,
    has_mobile_bridge_features,
    get_native_upload_dependencies,
    has_native_upload_features,
)
from .utils import create_mobile_app, create_site


class MobileAppServiceTests(TestCase):
    def setUp(self):
        self.site = create_site()
        self.mobile_app = create_mobile_app(
            self.site,
            enable_push_notifications=True,
            enable_camera_uploads=True,
            enable_file_picker=True,
            enable_share_sheet=True,
            enable_qr_scanner=True,
            enable_secure_storage=True,
            enable_deep_links=True,
        )

    def test_capability_statuses_include_all_flags(self):
        statuses = build_capability_statuses(self.mobile_app)
        self.assertEqual(len(statuses), 14)
        enabled = {status["key"] for status in statuses if status["enabled"]}
        self.assertIn("push_notifications", enabled)
        self.assertIn("camera", enabled)
        self.assertIn("file_picker", enabled)
        self.assertIn("share_sheet", enabled)
        self.assertIn("qr_scanner", enabled)
        self.assertIn("secure_storage", enabled)
        self.assertIn("deep_links", enabled)
        self.assertIn("offline", enabled)
        self.assertIn("external_links", enabled)

    def test_capability_registry_exposes_status_platforms_and_packages(self):
        registry = get_capability_registry()
        capability_map = {capability.key: capability for capability in registry}
        self.assertIn("camera", capability_map)
        self.assertIn("pwa", capability_map)
        self.assertIn("analytics", capability_map)
        self.assertEqual(capability_map["camera"].implementation_status, "implemented")
        self.assertTrue(capability_map["camera"].runtime_verification_required)
        self.assertEqual(
            capability_map["camera"].required_capacitor_packages,
            ("@capacitor/camera",),
        )
        self.assertEqual(
            capability_map["pwa"].supported_platforms,
            ("web", "android", "ios"),
        )

    def test_capability_metadata_contains_permission_and_package_guidance(self):
        metadata = build_capability_metadata(self.mobile_app)
        self.assertIn(
            "@capacitor/push-notifications",
            metadata["recommended_capacitor_packages"],
        )
        self.assertIn("@capacitor/camera", metadata["recommended_capacitor_packages"])
        self.assertIn("@capacitor/share", metadata["recommended_capacitor_packages"])
        self.assertIn(
            "@capacitor-mlkit/barcode-scanning",
            metadata["recommended_capacitor_packages"],
        )
        self.assertIn(
            "capacitor-secure-storage-plugin",
            metadata["recommended_capacitor_packages"],
        )
        self.assertEqual(
            json.loads(json.dumps(metadata))["enabled_capability_keys"],
            metadata["enabled_capability_keys"],
        )
        self.assertTrue(metadata["registry"])
        self.assertIn("camera", metadata["implemented_capability_keys"])
        self.assertIn("share_sheet", metadata["implemented_capability_keys"])
        self.assertIn("qr_scanner", metadata["implemented_capability_keys"])
        self.assertIn("secure_storage", metadata["implemented_capability_keys"])
        self.assertIn("push_notifications", metadata["planned_capability_keys"])
        self.assertIn("downloads", metadata["experimental_capability_keys"])
        self.assertTrue(
            any(
                item["key"] == "camera" and item["runtime_verification_required"]
                for item in metadata["runtime_verification_required"]
            )
        )
        self.assertTrue(metadata["permission_placeholders"]["android"])
        self.assertTrue(metadata["permission_placeholders"]["ios"])

    def test_native_upload_dependency_helpers(self):
        self.assertTrue(has_native_upload_features(self.mobile_app))
        self.assertTrue(has_mobile_bridge_features(self.mobile_app))
        self.assertEqual(
            get_native_upload_dependencies(self.mobile_app),
            ["@capacitor/camera", "@capawesome/capacitor-file-picker"],
        )
        self.assertEqual(
            get_mobile_bridge_dependencies(self.mobile_app),
            [
                "@capacitor/camera",
                "@capawesome/capacitor-file-picker",
                "@capacitor/share",
                "@capacitor-mlkit/barcode-scanning",
                "capacitor-secure-storage-plugin",
            ],
        )

    def test_mobile_bridge_script_contains_capacitor_and_browser_fallbacks(self):
        bridge_js = build_mobile_bridge_script(self.mobile_app)
        self.assertIn("window.MandelMobileApp", bridge_js)
        self.assertIn("Capacitor?.Plugins?.Camera", bridge_js)
        self.assertIn("Capacitor?.Plugins?.FilePicker", bridge_js)
        self.assertIn("Capacitor?.Plugins?.Share", bridge_js)
        self.assertIn("Capacitor?.Plugins?.BarcodeScanner", bridge_js)
        self.assertIn("Capacitor?.Plugins?.SecureStoragePlugin", bridge_js)
        self.assertIn("navigator.share", bridge_js)
        self.assertIn('input.type = "file"', bridge_js)
        self.assertIn("browser_input_unavailable", bridge_js)
        self.assertIn("selection_cancelled", bridge_js)
        self.assertIn("shareCurrentPage", bridge_js)
        self.assertIn("share_not_supported", bridge_js)
        self.assertIn("scanQrCode", bridge_js)
        self.assertIn("qr_scanner_not_supported", bridge_js)
        self.assertIn("secureStorage", bridge_js)
        self.assertIn("secure_storage_not_supported", bridge_js)
        self.assertIn("memory_ephemeral", bridge_js)
        self.assertIn('window.addEventListener("focus"', bridge_js)

    def test_generate_branding_assets_creates_manifest_and_icons(self):
        from pathlib import Path
        from tempfile import TemporaryDirectory

        with TemporaryDirectory() as tempdir:
            with override_settings(BASE_DIR=Path(tempdir)):
                result = generate_branding_assets(
                    self.site,
                    self.mobile_app,
                    Path(tempdir) / "mobile_apps" / f"site_{self.site.pk}" / "assets",
                )
                self.assertTrue(result["adaptive_icon_generated"])
                self.assertIn("branding.json", result["generated_files"])
                statuses = build_branding_asset_statuses(self.site.pk)
                self.assertTrue(
                    any(
                        entry["filename"] == "branding.json" and entry["exists"]
                        for entry in statuses
                    )
                )
                self.assertIn("adaptiveIcons", result["branding_manifest"])
                self.assertEqual(
                    result["branding_manifest"]["adaptiveIcons"]["foreground"],
                    "adaptive-icon-foreground.png",
                )
