"""Tests for security domain-inspired security patterns."""

from __future__ import annotations

from datetime import datetime
from pathlib import Path

import pytest

from gaol.domains import (
    DEFAULT_DOMAIN_POLICIES,
    DOMAIN_COLORS,
    DisposableConfig,
    DisposableInstance,
    DisposableType,
    DomainPolicy,
    SecurityDomain,
    TemplateConfig,
    TemplateInstance,
    TemplateState,
    TemplateType,
)
from gaol.domains.models import DisposableStore, DomainStore, TemplateStore


class TestTemplateModels:
    """Tests for template container models."""

    def test_template_config_defaults(self):
        """Test TemplateConfig with defaults."""
        config = TemplateConfig(name="test-template")
        assert config.name == "test-template"
        assert config.distro == "trixie"
        assert config.template_type == TemplateType.APP
        assert config.profiles == []
        assert config.packages == []

    def test_template_config_with_values(self):
        """Test TemplateConfig with custom values."""
        config = TemplateConfig(
            name="dev-template",
            distro="bookworm",
            profiles=["base", "dev-python"],
            packages=["vim", "git"],
            template_type=TemplateType.SYSTEM,
            description="Development template",
            default_memory_mb=4096,
            default_cpu_count=2.0,
        )
        assert config.name == "dev-template"
        assert config.distro == "bookworm"
        assert config.profiles == ["base", "dev-python"]
        assert config.packages == ["vim", "git"]
        assert config.template_type == TemplateType.SYSTEM
        assert config.description == "Development template"
        assert config.default_memory_mb == 4096
        assert config.default_cpu_count == 2.0

    def test_template_state(self):
        """Test TemplateState model."""
        state = TemplateState(
            name="test",
            distro="trixie",
            template_type=TemplateType.APP,
            root_path=Path("/var/lib/gaol/templates/test"),
        )
        assert state.name == "test"
        assert state.version == 1
        assert state.instances == []
        assert state.size_bytes == 0

    def test_template_instance(self):
        """Test TemplateInstance model."""
        instance = TemplateInstance(
            name="test-instance",
            template_name="test",
            template_version=1,
            ephemeral=True,
        )
        assert instance.name == "test-instance"
        assert instance.template_name == "test"
        assert instance.ephemeral is True
        assert instance.preserve_paths == []


class TestDisposableModels:
    """Tests for disposable container models."""

    def test_disposable_config_minimal(self):
        """Test DisposableConfig with minimal values."""
        config = DisposableConfig(
            name="browser",
            template_name="debian-browser",
        )
        assert config.name == "browser"
        assert config.template_name == "debian-browser"
        assert config.disposable_type == DisposableType.CUSTOM
        assert config.application is None
        assert config.preserve_downloads is False

    def test_disposable_config_full(self):
        """Test DisposableConfig with all values."""
        config = DisposableConfig(
            name="secure-browser",
            template_name="debian-browser",
            disposable_type=DisposableType.BROWSER,
            application="/usr/bin/firefox",
            application_args=["--private"],
            icon="firefox",
            icon_color="#CC0000",
            desktop_name="Secure Browser",
            desktop_categories=["Network"],
            mime_types=["text/html"],
            preserve_downloads=True,
            preserve_paths=["~/.config/app"],
            domain="untrusted",
            allow_network=True,
        )
        assert config.disposable_type == DisposableType.BROWSER
        assert config.application == "/usr/bin/firefox"
        assert config.icon_color == "#CC0000"
        assert config.preserve_downloads is True

    def test_disposable_instance(self):
        """Test DisposableInstance model."""
        instance = DisposableInstance(
            instance_id="disp-browser-1234",
            disposable_name="browser",
            template_name="debian-browser",
            container_name="disp-browser-1234",
        )
        assert instance.instance_id == "disp-browser-1234"
        assert instance.arguments == []


class TestSecurityDomains:
    """Tests for security domain models."""

    def test_domain_colors(self):
        """Test default domain colors."""
        assert SecurityDomain.VAULT in DOMAIN_COLORS
        assert SecurityDomain.WORK in DOMAIN_COLORS
        assert SecurityDomain.SELF_HOSTED in DOMAIN_COLORS
        assert SecurityDomain.UNTRUSTED in DOMAIN_COLORS
        # Vault is purple
        assert DOMAIN_COLORS[SecurityDomain.VAULT] == "#800080"
        # Self-hosted is orange
        assert DOMAIN_COLORS[SecurityDomain.SELF_HOSTED] == "#FF8C00"
        # Untrusted is red
        assert DOMAIN_COLORS[SecurityDomain.UNTRUSTED] == "#CC0000"

    def test_default_policies(self):
        """Test default domain policies."""
        vault_policy = DEFAULT_DOMAIN_POLICIES[SecurityDomain.VAULT]
        assert vault_policy.allow_network is False
        assert vault_policy.allow_internet is False

        work_policy = DEFAULT_DOMAIN_POLICIES[SecurityDomain.WORK]
        assert work_policy.allow_network is True
        assert work_policy.allow_internet is True

        self_hosted_policy = DEFAULT_DOMAIN_POLICIES[SecurityDomain.SELF_HOSTED]
        assert self_hosted_policy.allow_network is True
        assert self_hosted_policy.allow_internet is True
        assert self_hosted_policy.ephemeral_only is False
        assert self_hosted_policy.read_only_root is False
        assert SecurityDomain.PERSONAL in self_hosted_policy.allow_communication_with
        assert SecurityDomain.WORK in self_hosted_policy.allow_communication_with

        untrusted_policy = DEFAULT_DOMAIN_POLICIES[SecurityDomain.UNTRUSTED]
        assert untrusted_policy.read_only_root is True
        assert untrusted_policy.max_memory_mb == 2048

        disp_policy = DEFAULT_DOMAIN_POLICIES[SecurityDomain.DISPOSABLE]
        assert disp_policy.ephemeral_only is True

    def test_custom_domain_policy(self):
        """Test creating a custom domain policy."""
        policy = DomainPolicy(
            domain=SecurityDomain.WORK,
            color="#0066B3",
            allow_network=True,
            allow_internet=True,
            required_gateway="vpn-gateway",
            max_memory_mb=8192,
        )
        assert policy.domain == SecurityDomain.WORK
        assert policy.required_gateway == "vpn-gateway"
        assert policy.max_memory_mb == 8192


class TestStores:
    """Tests for store models."""

    def test_template_store(self):
        """Test TemplateStore operations."""
        store = TemplateStore()
        assert store.list_templates() == []

        template = TemplateState(
            name="test",
            distro="trixie",
            template_type=TemplateType.APP,
            root_path=Path("/tmp/test"),
        )
        store.add_template(template)

        assert store.get_template("test") is not None
        assert len(store.list_templates()) == 1
        assert store.remove_template("test") is True
        assert store.get_template("test") is None

    def test_disposable_store(self):
        """Test DisposableStore operations."""
        store = DisposableStore()
        assert store.list_disposables() == []

        config = DisposableConfig(
            name="browser",
            template_name="debian-browser",
        )
        store.add_disposable(config)

        assert store.get_disposable("browser") is not None
        assert len(store.list_disposables()) == 1
        assert store.remove_disposable("browser") is True

    def test_domain_store(self):
        """Test DomainStore operations."""
        store = DomainStore()

        # Test default policy retrieval
        policy = store.get_policy(SecurityDomain.VAULT)
        assert policy.allow_network is False

        # Test container assignment
        store.assign_container("my-vault", SecurityDomain.VAULT)
        assert store.get_container_domain("my-vault") == SecurityDomain.VAULT

        containers = store.list_containers_in_domain(SecurityDomain.VAULT)
        assert "my-vault" in containers

        # Test unassign
        assert store.unassign_container("my-vault") is True
        assert store.get_container_domain("my-vault") is None


class TestDisposableTypes:
    """Tests for disposable type enum."""

    def test_disposable_types(self):
        """Test all disposable types."""
        assert DisposableType.BROWSER.value == "browser"
        assert DisposableType.FILE_VIEWER.value == "file_viewer"
        assert DisposableType.TERMINAL.value == "terminal"
        assert DisposableType.CUSTOM.value == "custom"


class TestTemplateTypes:
    """Tests for template type enum."""

    def test_template_types(self):
        """Test all template types."""
        assert TemplateType.SYSTEM.value == "system"
        assert TemplateType.APP.value == "app"
        assert TemplateType.MINIMAL.value == "minimal"
        assert TemplateType.NETWORK.value == "network"
