"""Tests for integrations app models."""

import pytest
from django.db import IntegrityError
from django.utils import timezone

from .factories import GitHubInstallationFactory, GitHubRepositoryFactory


@pytest.mark.django_db
class TestGitHubInstallation:
    """Tests for the GitHubInstallation model."""

    def test_create_installation(self):
        """Test creating a GitHub installation with the factory."""
        installation = GitHubInstallationFactory()
        assert installation.pk is not None
        assert installation.workspace is not None
        assert installation.installation_id is not None

    def test_installation_str(self):
        """Test installation string representation."""
        installation = GitHubInstallationFactory(account_login="acme-corp", account_type="Organization")
        assert str(installation) == "acme-corp (Organization)"

    def test_installation_account_types(self):
        """Test installation with different account types."""
        user_inst = GitHubInstallationFactory(account_type="User")
        org_inst = GitHubInstallationFactory(account_type="Organization")
        assert user_inst.account_type == "User"
        assert org_inst.account_type == "Organization"

    def test_installation_unique_installation_id(self):
        """Test that installation_id must be unique."""
        GitHubInstallationFactory(installation_id=12345)
        with pytest.raises(IntegrityError):
            GitHubInstallationFactory(installation_id=12345)

    def test_installation_one_per_workspace(self):
        """Test that each workspace can only have one installation."""
        installation = GitHubInstallationFactory()
        with pytest.raises(IntegrityError):
            GitHubInstallationFactory(workspace=installation.workspace)

    def test_installation_is_suspended(self):
        """Test is_suspended property."""
        active = GitHubInstallationFactory(suspended_at=None)
        suspended = GitHubInstallationFactory(suspended_at=timezone.now())
        assert active.is_suspended is False
        assert suspended.is_suspended is True

    def test_installation_access_token_encryption(self):
        """Test that access token is encrypted and decrypted correctly."""
        installation = GitHubInstallationFactory()
        installation.access_token = "ghs_test_token_123"
        installation.save()

        # Reload from database
        installation.refresh_from_db()

        # Token should be decrypted correctly
        assert installation.access_token == "ghs_test_token_123"
        # Stored value should be different (encrypted)
        assert installation._access_token != "ghs_test_token_123"

    def test_installation_access_token_is_fernet_encrypted(self):
        """Test that access token uses Fernet encryption (not signing)."""
        from core.utils.encryption import is_encrypted

        installation = GitHubInstallationFactory()
        installation.access_token = "ghs_secret_token_abc"
        installation.save()

        installation.refresh_from_db()

        # Stored value should be Fernet-encrypted (starts with gAAAAA)
        assert is_encrypted(installation._access_token)
        # Original token should NOT be visible in the stored value
        assert "ghs_secret_token_abc" not in installation._access_token

    def test_installation_empty_access_token(self):
        """Test empty access token."""
        installation = GitHubInstallationFactory()
        installation.access_token = ""
        assert installation.access_token == ""

    def test_installation_with_permissions(self):
        """Test installation with permissions."""
        permissions = {"contents": "read", "issues": "write"}
        installation = GitHubInstallationFactory(permissions=permissions)
        assert installation.permissions == permissions

    def test_installation_has_timestamps(self):
        """Test that installation has created_at and updated_at."""
        installation = GitHubInstallationFactory()
        assert installation.created_at is not None
        assert installation.updated_at is not None


@pytest.mark.django_db
class TestGitHubRepository:
    """Tests for the GitHubRepository model."""

    def test_create_repository(self):
        """Test creating a GitHub repository with the factory."""
        repo = GitHubRepositoryFactory()
        assert repo.pk is not None
        assert repo.installation is not None
        assert repo.source is not None

    def test_repository_str(self):
        """Test repository string representation."""
        repo = GitHubRepositoryFactory(full_name="acme/my-project")
        assert str(repo) == "acme/my-project"

    def test_repository_html_url(self):
        """Test repository html_url property."""
        repo = GitHubRepositoryFactory(full_name="acme/my-project")
        assert repo.html_url == "https://github.com/acme/my-project"

    def test_repository_default_sync_status(self):
        """Test repository default sync status is pending."""
        repo = GitHubRepositoryFactory()
        assert repo.sync_status == "pending"

    def test_repository_sync_status_choices(self):
        """Test repository with different sync status choices."""
        statuses = ["pending", "syncing", "active", "error", "paused", "disabled"]
        for status in statuses:
            repo = GitHubRepositoryFactory(sync_status=status)
            assert repo.sync_status == status

    def test_repository_unique_installation_repo_id(self):
        """Test that installation + repo_id must be unique."""
        repo = GitHubRepositoryFactory(repo_id=12345)
        with pytest.raises(IntegrityError):
            GitHubRepositoryFactory(installation=repo.installation, repo_id=12345)

    def test_repository_same_repo_id_different_installation(self):
        """Test same repo_id with different installation is allowed."""
        repo1 = GitHubRepositoryFactory(repo_id=12345)
        repo2 = GitHubRepositoryFactory(repo_id=12345)
        assert repo1.installation != repo2.installation

    def test_repository_private_flag(self):
        """Test repository private flag."""
        public = GitHubRepositoryFactory(private=False)
        private = GitHubRepositoryFactory(private=True)
        assert public.private is False
        assert private.private is True

    def test_repository_is_archived(self):
        """Test repository is_archived flag."""
        active = GitHubRepositoryFactory(is_archived=False)
        archived = GitHubRepositoryFactory(is_archived=True)
        assert active.is_archived is False
        assert archived.is_archived is True

    def test_repository_with_sync_cursors(self):
        """Test repository with sync cursors."""
        cursors = {"issues": "cursor123", "pulls": "cursor456"}
        repo = GitHubRepositoryFactory(sync_cursors=cursors)
        assert repo.sync_cursors == cursors

    def test_repository_with_sync_error(self):
        """Test repository with sync error."""
        repo = GitHubRepositoryFactory(sync_status="error", last_sync_error="Rate limit exceeded")
        assert repo.sync_status == "error"
        assert repo.last_sync_error == "Rate limit exceeded"

    def test_repository_has_timestamps(self):
        """Test that repository has created_at and updated_at."""
        repo = GitHubRepositoryFactory()
        assert repo.created_at is not None
        assert repo.updated_at is not None

    def test_repository_belongs_to_installation(self):
        """Test repository belongs to an installation."""
        repo = GitHubRepositoryFactory()
        assert repo.installation is not None
        assert repo in repo.installation.repositories.all()
