from django.template import Context, Template
from django.test import Client, TestCase, override_settings

from .utils import create_mobile_app, create_site, create_staff_user


class MobileAppViewTests(TestCase):
    def setUp(self):
        self.site = create_site()
        self.mobile_app = create_mobile_app(self.site)
        self.client = Client()

    def test_manifest_generation(self):
        response = self.client.get("/manifest.json", HTTP_HOST=self.site.hostname)
        self.assertEqual(response.status_code, 200)
        payload = response.json()
        self.assertEqual(payload["name"], "Example App")
        self.assertEqual(payload["display"], "standalone")
        self.assertTrue(payload["icons"])

    def test_service_worker_response(self):
        response = self.client.get("/serviceworker.js", HTTP_HOST=self.site.hostname)
        self.assertEqual(response.status_code, 200)
        self.assertIn("OFFLINE_URL", response.content.decode())
        self.assertIn("/admin/", response.content.decode())

    def test_offline_page_has_safe_area_and_state_copy(self):
        response = self.client.get("/offline/", HTTP_HOST=self.site.hostname)
        self.assertEqual(response.status_code, 200)
        content = response.content.decode()
        self.assertIn("viewport-fit=cover", content)
        self.assertIn("Offline mode", content)
        self.assertIn("mobileapp/css/offline.css", content)

    def test_disabled_pwa_behavior(self):
        self.mobile_app.enable_pwa = False
        self.mobile_app.save(update_fields=["enable_pwa"])
        manifest_response = self.client.get(
            "/manifest.json", HTTP_HOST=self.site.hostname
        )
        worker_response = self.client.get(
            "/serviceworker.js", HTTP_HOST=self.site.hostname
        )
        self.assertEqual(manifest_response.status_code, 404)
        self.assertIn("disabled", worker_response.content.decode())

    def test_multisite_behavior(self):
        second_site = create_site("second.example.com", "Second", False)
        create_mobile_app(second_site, name="Second App", short_name="Second")
        response = self.client.get("/manifest.json", HTTP_HOST="second.example.com")
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json()["name"], "Second App")

    def test_template_tags_render(self):
        template = Template(
            "{% load mobile_app_tags %}{% mobile_app_head %}{% mobile_app_service_worker %}{% mobile_app_bridge %}"
        )
        request = self.client.get("/", HTTP_HOST=self.site.hostname).wsgi_request
        rendered = template.render(Context({"request": request}))
        self.assertIn('rel="manifest"', rendered)
        self.assertIn("serviceWorker.register", rendered)

    def test_mobile_app_bridge_renders_empty_when_uploads_disabled(self):
        template = Template("{% load mobile_app_tags %}{% mobile_app_bridge %}")
        request = self.client.get("/", HTTP_HOST=self.site.hostname).wsgi_request
        rendered = template.render(Context({"request": request}))
        self.assertEqual(rendered.strip(), "")

    def test_mobile_app_bridge_renders_script_when_bridge_features_enabled(self):
        self.mobile_app.enable_qr_scanner = True
        self.mobile_app.enable_secure_storage = True
        self.mobile_app.save(
            update_fields=["enable_qr_scanner", "enable_secure_storage"]
        )
        template = Template("{% load mobile_app_tags %}{% mobile_app_bridge %}")
        request = self.client.get("/", HTTP_HOST=self.site.hostname).wsgi_request
        rendered = template.render(Context({"request": request}))
        self.assertIn("window.MandelMobileApp", rendered)
        self.assertIn("scanQrCode", rendered)
        self.assertIn("qr_scanner_not_supported", rendered)
        self.assertIn("secureStorage", rendered)
        self.assertIn("secure_storage_not_supported", rendered)


class MobileAppAdminTests(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_geolocation=True,
            enable_share_sheet=True,
            enable_qr_scanner=True,
            enable_secure_storage=True,
            enable_deep_links=True,
        )
        self.staff_user = create_staff_user()
        self.client = Client()

    def test_admin_dashboard_requires_staff(self):
        response = self.client.get("/admin/mobile-app/")
        self.assertEqual(response.status_code, 302)

    def test_admin_dashboard_staff_access(self):
        self.client.force_login(self.staff_user)
        response = self.client.get("/admin/mobile-app/")
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Mobile App")
        self.assertContains(response, "Branding asset readiness")
        self.assertContains(response, "App icon present")
        self.assertContains(response, "Splash image present")
        self.assertContains(response, "Adaptive icon generated")
        self.assertContains(response, "Native capability planning")
        self.assertContains(response, "Push notifications")
        self.assertContains(response, "Camera")
        self.assertContains(response, "Share sheet")
        self.assertContains(response, "QR scanner")
        self.assertContains(response, "Secure storage")
        self.assertContains(response, "Deep link planning")
        self.assertContains(response, "Required Capacitor packages")
        self.assertContains(response, "Enabled capabilities")
        self.assertContains(response, "Planned capabilities")
        self.assertContains(response, "Runtime verification backlog")
        self.assertContains(response, "implemented")
        self.assertContains(response, "planned")
        self.assertContains(response, "web, android, ios")
        self.assertContains(response, "Bridge tag")
        self.assertContains(response, "Generated native upload dependencies")
        self.assertContains(response, "Generated bridge dependencies")
        self.assertContains(
            response,
            "Secure storage backend",
        )
        self.assertContains(
            response,
            "Warning: camera uploads are enabled but the iOS camera usage description is still empty.",
        )
        self.assertContains(
            response,
            "QR scanner is enabled, but the iOS camera usage description is still empty.",
        )
        self.assertContains(response, "App version")
        self.assertContains(response, "Build number")
        self.assertContains(response, "Runtime policies")
        self.assertContains(response, "open_in_system_browser")
        self.assertContains(response, "window.MandelMobileAppDiagnostics")
        self.assertContains(response, "@capacitor/share")
        self.assertContains(response, "@capacitor-mlkit/barcode-scanning")
        self.assertContains(response, "capacitor-secure-storage-plugin")
        self.assertContains(
            response,
            "native_secure_storage_or_memory_ephemeral_fallback",
        )
        self.assertContains(response, "PWA / offline readiness")
        self.assertContains(response, "dist/manifest.webmanifest")
        self.assertContains(response, "dist/service-worker.js")

    def test_admin_dashboard_shows_generated_branding_assets_after_generation(self):
        from pathlib import Path
        from tempfile import TemporaryDirectory
        from ..services import generate_capacitor_project

        self.client.force_login(self.staff_user)
        with TemporaryDirectory() as tempdir:
            with override_settings(BASE_DIR=Path(tempdir)):
                generate_capacitor_project(self.site, self.mobile_app)
                response = self.client.get("/admin/mobile-app/")
                self.assertContains(response, "branding.json")
                self.assertContains(response, "adaptive-icon.png")

    def test_settings_model_exposes_native_capability_fields(self):
        field_names = {
            field.name
            for field in self.mobile_app._meta.get_fields()
            if hasattr(field, "name")
        }
        self.assertTrue(
            {
                "enable_push_notifications",
                "enable_camera_uploads",
                "enable_file_picker",
                "enable_geolocation",
                "enable_qr_scanner",
                "enable_secure_storage",
                "enable_biometrics",
                "enable_share_sheet",
                "enable_deep_links",
                "app_version",
                "build_number",
            }.issubset(field_names)
        )
