"""
Tests for Database Schema Migrations

Phase 21: Database & Encryption - Schema Migration Tests
Tests database schema creation, versioning, and migrations.
"""

import pytest


class TestSchemaMigrations:
    """Tests for schema migration functionality"""

    def test_initial_schema_creation(self):
        """Test initial schema is created correctly"""
        from local_deep_research.database.models import Base

        # Verify Base.metadata has tables defined
        assert len(Base.metadata.tables) > 0

    def test_migration_models_importable(self):
        """Test all model modules can be imported"""
        # Import each model module to ensure no syntax errors
        from local_deep_research.database.models import auth
        from local_deep_research.database.models import research
        from local_deep_research.database.models import settings
        from local_deep_research.database.models import cache
        from local_deep_research.database.models import metrics
        from local_deep_research.database.models import queue

        assert auth is not None
        assert research is not None
        assert settings is not None
        assert cache is not None
        assert metrics is not None
        assert queue is not None

    def test_base_model_columns(self):
        """Test base model has expected columns"""
        from local_deep_research.database.models.base import Base

        # Base should be a declarative base
        assert hasattr(Base, "metadata")

    def test_auth_model_schema(self):
        """Test auth model schema"""
        from local_deep_research.database.models.auth import User

        # Check expected columns exist
        columns = User.__table__.columns.keys()

        assert "id" in columns
        assert "username" in columns
        # Note: passwords are NOT stored in this model - they decrypt user databases

    def test_research_model_schema(self):
        """Test research model schema"""
        from local_deep_research.database.models.research import ResearchHistory

        columns = ResearchHistory.__table__.columns.keys()

        assert "id" in columns
        assert "query" in columns
        assert "status" in columns

    def test_settings_model_schema(self):
        """Test settings model schema"""
        from local_deep_research.database.models.settings import Setting

        columns = Setting.__table__.columns.keys()

        assert "id" in columns
        assert "key" in columns
        assert "value" in columns

    def test_cache_model_schema(self):
        """Test cache model schema"""
        from local_deep_research.database.models.cache import Cache

        columns = Cache.__table__.columns.keys()

        assert "id" in columns
        assert "cache_key" in columns  # Actual column name

    def test_metrics_model_schema(self):
        """Test metrics model schema"""
        from local_deep_research.database.models.metrics import TokenUsage

        columns = TokenUsage.__table__.columns.keys()

        assert "id" in columns

    def test_sorted_tables_order(self):
        """Test tables are sorted correctly for creation"""
        from local_deep_research.database.models import Base

        tables = Base.metadata.sorted_tables

        # Should have multiple tables
        assert len(tables) > 0

        # Tables should be sorted by dependency order
        table_names = [t.name for t in tables]
        assert len(table_names) == len(set(table_names))  # No duplicates


class TestModelRelationships:
    """Tests for model relationships"""

    def test_research_source_relationship(self):
        """Test research model has expected columns"""
        from local_deep_research.database.models.research import ResearchHistory

        # Check research history model exists and has expected columns
        columns = ResearchHistory.__table__.columns.keys()
        assert "id" in columns
        assert "query" in columns

    def test_queued_research_relationship(self):
        """Test queued research model"""
        from local_deep_research.database.models.queued_research import (
            QueuedResearch,
        )

        columns = QueuedResearch.__table__.columns.keys()

        assert "id" in columns
        assert "query" in columns


class TestDatabaseInitialization:
    """Tests for database initialization"""

    def test_initialize_database_function_exists(self):
        """Test initialize_database function exists"""
        from local_deep_research.database.initialize import initialize_database

        assert callable(initialize_database)

    def test_initialize_module_importable(self):
        """Test initialize module can be imported"""
        from local_deep_research.database import initialize

        assert hasattr(initialize, "initialize_database")


class TestConstraints:
    """Tests for database constraints"""

    def test_unique_username_constraint(self):
        """Test unique username constraint on User model"""
        from local_deep_research.database.models.auth import User

        # Check for unique constraint on username
        username_col = User.__table__.columns["username"]
        assert username_col.unique is True

    def test_setting_key_uniqueness(self):
        """Test setting key uniqueness"""
        from local_deep_research.database.models.settings import Setting

        # Key should be unique within user context
        _key_col = Setting.__table__.columns["key"]  # noqa: F841
        # May have unique constraint or unique together with user_id


class TestColumnTypes:
    """Tests for column type definitions"""

    def test_datetime_columns_have_timezone(self):
        """Test datetime columns use timezone-aware type"""
        from local_deep_research.database.models.research import ResearchHistory

        # Check created_at column exists
        if "created_at" in ResearchHistory.__table__.columns:
            created_col = ResearchHistory.__table__.columns["created_at"]
            # Column should exist (type checking varies by dialect)
            assert created_col is not None

    def test_text_columns_for_long_content(self):
        """Test long content uses Text type"""
        from local_deep_research.database.models.research import ResearchHistory

        # Check report column uses Text
        if "report" in ResearchHistory.__table__.columns:
            report_col = ResearchHistory.__table__.columns["report"]
            assert report_col is not None

    def test_json_columns(self):
        """Test JSON column support"""
        from local_deep_research.database.models.settings import Setting

        # Settings may store JSON values
        value_col = Setting.__table__.columns["value"]
        assert value_col is not None


class TestIndexes:
    """Tests for database indexes"""

    def test_primary_key_indexes(self):
        """Test primary key columns are indexed"""
        from local_deep_research.database.models.auth import User

        # Primary key should be indexed by default
        id_col = User.__table__.columns["id"]
        assert id_col.primary_key is True

    def test_foreign_key_references(self):
        """Test foreign key relationships exist"""
        from local_deep_research.database.models.research import ResearchHistory

        # Check that research history model exists and is properly defined
        assert ResearchHistory.__tablename__ is not None


class TestTableNames:
    """Tests for table naming conventions"""

    def test_table_names_lowercase(self):
        """Test table names are lowercase"""
        from local_deep_research.database.models import Base

        for table in Base.metadata.tables.values():
            assert table.name == table.name.lower()

    def test_no_reserved_keywords(self):
        """Test no reserved SQL keywords used as table names"""
        reserved = {"user", "order", "group", "select", "table", "index"}

        from local_deep_research.database.models import Base

        for table in Base.metadata.tables.values():
            # 'users' is fine, 'user' is reserved
            if table.name in reserved:
                pytest.fail(
                    f"Reserved keyword used as table name: {table.name}"
                )
