# tests/integration/api/v1/admin/test_modules.py
"""
Integration tests for admin module management endpoints.

Tests the /api/v1/admin/modules/* and /api/v1/admin/module-config/* endpoints.
All endpoints require super admin access.
"""

import pytest


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
@pytest.mark.modules
class TestAdminModulesAPI:
    """Tests for admin module management endpoints."""

    # ========================================================================
    # List Modules Tests
    # ========================================================================

    def test_list_all_modules(self, client, super_admin_headers):
        """Test super admin listing all modules."""
        response = client.get("/api/v1/admin/modules", headers=super_admin_headers)

        assert response.status_code == 200
        data = response.json()
        assert "modules" in data
        assert "total" in data
        assert data["total"] >= 10  # At least 10 modules defined

        # Check expected modules exist
        module_codes = [m["code"] for m in data["modules"]]
        assert "core" in module_codes
        assert "billing" in module_codes
        assert "inventory" in module_codes

    def test_list_modules_requires_super_admin(self, client, admin_headers):
        """Test that listing modules requires super admin."""
        response = client.get("/api/v1/admin/modules", headers=admin_headers)

        # Should require super admin
        assert response.status_code == 403

    def test_list_modules_unauthenticated(self, client):
        """Test that listing modules requires authentication."""
        response = client.get("/api/v1/admin/modules")

        assert response.status_code == 401

    # ========================================================================
    # Get Platform Modules Tests
    # ========================================================================

    def test_get_platform_modules(self, client, super_admin_headers, test_platform):
        """Test getting modules for a specific platform."""
        response = client.get(
            f"/api/v1/admin/modules/platforms/{test_platform.id}",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["platform_id"] == test_platform.id
        assert data["platform_code"] == test_platform.code
        assert "modules" in data
        assert "enabled" in data
        assert "disabled" in data

    def test_get_platform_modules_not_found(self, client, super_admin_headers):
        """Test getting modules for non-existent platform."""
        response = client.get(
            "/api/v1/admin/modules/platforms/99999",
            headers=super_admin_headers,
        )

        assert response.status_code == 404

    # ========================================================================
    # Enable/Disable Module Tests
    # ========================================================================

    def test_enable_module(self, client, super_admin_headers, test_platform, db):
        """Test enabling a module for a platform."""
        # First disable the module via settings
        test_platform.settings = {"enabled_modules": ["core", "platform-admin"]}
        db.commit()

        response = client.post(
            f"/api/v1/admin/modules/platforms/{test_platform.id}/enable",
            headers=super_admin_headers,
            json={"module_code": "billing"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True
        assert "billing" in data["message"].lower() or "enabled" in data["message"].lower()

    def test_disable_module(self, client, super_admin_headers, test_platform, db):
        """Test disabling a module for a platform."""
        # Ensure module is enabled
        test_platform.settings = {"enabled_modules": ["billing", "inventory"]}
        db.commit()

        response = client.post(
            f"/api/v1/admin/modules/platforms/{test_platform.id}/disable",
            headers=super_admin_headers,
            json={"module_code": "billing"},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True

    def test_cannot_disable_core_module(self, client, super_admin_headers, test_platform):
        """Test that core modules cannot be disabled."""
        response = client.post(
            f"/api/v1/admin/modules/platforms/{test_platform.id}/disable",
            headers=super_admin_headers,
            json={"module_code": "core"},
        )

        assert response.status_code == 400
        data = response.json()
        assert "core" in data.get("message", "").lower() or "cannot" in data.get("message", "").lower()

    def test_enable_invalid_module(self, client, super_admin_headers, test_platform):
        """Test enabling a non-existent module."""
        response = client.post(
            f"/api/v1/admin/modules/platforms/{test_platform.id}/enable",
            headers=super_admin_headers,
            json={"module_code": "invalid_module"},
        )

        assert response.status_code == 400

    # ========================================================================
    # Bulk Operations Tests
    # ========================================================================

    def test_update_platform_modules(self, client, super_admin_headers, test_platform):
        """Test updating all enabled modules at once."""
        response = client.put(
            f"/api/v1/admin/modules/platforms/{test_platform.id}",
            headers=super_admin_headers,
            json={"module_codes": ["billing", "inventory", "orders"]},
        )

        assert response.status_code == 200
        data = response.json()
        assert data["platform_id"] == test_platform.id

        # Check that specified modules are enabled
        enabled_codes = [m["code"] for m in data["modules"] if m["is_enabled"]]
        assert "billing" in enabled_codes
        assert "inventory" in enabled_codes
        assert "orders" in enabled_codes
        # Core modules should always be enabled
        assert "core" in enabled_codes

    def test_enable_all_modules(self, client, super_admin_headers, test_platform):
        """Test enabling all modules for a platform."""
        response = client.post(
            f"/api/v1/admin/modules/platforms/{test_platform.id}/enable-all",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True
        assert data["enabled_count"] >= 10

    def test_disable_optional_modules(self, client, super_admin_headers, test_platform):
        """Test disabling all optional modules."""
        response = client.post(
            f"/api/v1/admin/modules/platforms/{test_platform.id}/disable-optional",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True
        assert "core" in data["core_modules"]


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.admin
@pytest.mark.modules
class TestAdminModuleConfigAPI:
    """Tests for admin module configuration endpoints."""

    # ========================================================================
    # Get Module Config Tests
    # ========================================================================

    def test_get_module_config(self, client, super_admin_headers, test_platform):
        """Test getting module configuration."""
        response = client.get(
            f"/api/v1/admin/module-config/platforms/{test_platform.id}/modules/billing/config",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["module_code"] == "billing"
        assert "config" in data
        assert "schema_info" in data
        assert "defaults" in data

    def test_get_module_config_has_defaults(self, client, super_admin_headers, test_platform):
        """Test that module config includes default values."""
        response = client.get(
            f"/api/v1/admin/module-config/platforms/{test_platform.id}/modules/billing/config",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()

        # Should have default billing config
        assert "stripe_mode" in data["config"]
        assert "default_trial_days" in data["config"]

    def test_get_module_config_invalid_module(self, client, super_admin_headers, test_platform):
        """Test getting config for invalid module."""
        response = client.get(
            f"/api/v1/admin/module-config/platforms/{test_platform.id}/modules/invalid_module/config",
            headers=super_admin_headers,
        )

        assert response.status_code == 400

    # ========================================================================
    # Update Module Config Tests
    # ========================================================================

    def test_update_module_config(self, client, super_admin_headers, test_platform):
        """Test updating module configuration."""
        response = client.put(
            f"/api/v1/admin/module-config/platforms/{test_platform.id}/modules/billing/config",
            headers=super_admin_headers,
            json={
                "config": {
                    "stripe_mode": "live",
                    "default_trial_days": 7,
                }
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["config"]["stripe_mode"] == "live"
        assert data["config"]["default_trial_days"] == 7

    def test_update_module_config_persists(self, client, super_admin_headers, test_platform):
        """Test that config updates persist across requests."""
        # Update config
        client.put(
            f"/api/v1/admin/module-config/platforms/{test_platform.id}/modules/inventory/config",
            headers=super_admin_headers,
            json={
                "config": {
                    "low_stock_threshold": 25,
                }
            },
        )

        # Fetch again
        response = client.get(
            f"/api/v1/admin/module-config/platforms/{test_platform.id}/modules/inventory/config",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["config"]["low_stock_threshold"] == 25

    # ========================================================================
    # Reset Config Tests
    # ========================================================================

    def test_reset_module_config(self, client, super_admin_headers, test_platform):
        """Test resetting module config to defaults."""
        # First set custom config
        client.put(
            f"/api/v1/admin/module-config/platforms/{test_platform.id}/modules/billing/config",
            headers=super_admin_headers,
            json={
                "config": {
                    "stripe_mode": "live",
                    "default_trial_days": 1,
                }
            },
        )

        # Reset to defaults
        response = client.post(
            f"/api/v1/admin/module-config/platforms/{test_platform.id}/modules/billing/reset",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["success"] is True
        # Config should be reset to defaults
        assert data["config"]["stripe_mode"] == "test"
        assert data["config"]["default_trial_days"] == 14

    # ========================================================================
    # Get Defaults Tests
    # ========================================================================

    def test_get_config_defaults(self, client, super_admin_headers):
        """Test getting default config for a module."""
        response = client.get(
            "/api/v1/admin/module-config/defaults/billing",
            headers=super_admin_headers,
        )

        assert response.status_code == 200
        data = response.json()
        assert data["module_code"] == "billing"
        assert "defaults" in data
        assert "schema_info" in data
        assert data["defaults"]["stripe_mode"] == "test"
