"""
Worktable Tests - Model Tests.
"""
import pytest
from decimal import Decimal
from django.core.exceptions import ValidationError

from apps.services.worktable.models import (
    TableDefinition,
    TableColumn,
    TableRecord,
    SavedFilter,
    CustomView,
    RecordAuditLog,
    FieldType,
    RecordStatus,
    AuditAction,
)


@pytest.mark.django_db
class TestTableDefinition:
    """Tests for TableDefinition model."""

    def test_create_table_definition(self, tenant):
        """Test creating a table definition."""
        table = TableDefinition.objects.create(
            tenant=tenant,
            slug='employees',
            name='کارمندان',
            description='جدول کارمندان',
        )
        assert table.id is not None
        assert table.slug == 'employees'
        assert table.name == 'کارمندان'
        assert table.is_active is True

    def test_table_definition_str(self, table_definition):
        """Test string representation."""
        assert str(table_definition) == 'محصولات'

    def test_table_definition_unique_slug_per_tenant(self, tenant, table_definition):
        """Test that slug is unique per tenant."""
        from django.db import IntegrityError
        with pytest.raises(IntegrityError):
            TableDefinition.objects.create(
                tenant=tenant,
                slug='products',  # Same slug
                name='محصولات دیگر',
            )

    def test_table_definition_column_count(self, table_definition, table_columns):
        """Test column count property."""
        assert table_definition.column_count == 5

    def test_table_definition_record_count(self, table_definition, table_record):
        """Test record count property."""
        assert table_definition.record_count == 1

    def test_get_settings_with_defaults(self, table_definition):
        """Test get_default_settings returns defaults merged with custom settings."""
        settings = table_definition.get_default_settings()
        assert 'page_size' in settings
        assert settings['page_size'] == 20


@pytest.mark.django_db
class TestTableColumn:
    """Tests for TableColumn model."""

    def test_create_column(self, table_definition):
        """Test creating a column."""
        column = TableColumn.objects.create(
            table=table_definition,
            slug='email',
            name='ایمیل',
            field_type=FieldType.EMAIL,
            is_required=True,
        )
        assert column.id is not None
        assert column.field_type == FieldType.EMAIL

    def test_column_str(self, table_columns):
        """Test string representation."""
        column = table_columns[0]
        assert 'نام محصول' in str(column)

    def test_column_unique_slug_per_table(self, table_definition, table_columns):
        """Test that slug is unique per table."""
        from django.db import IntegrityError
        with pytest.raises(IntegrityError):
            TableColumn.objects.create(
                table=table_definition,
                slug='name',  # Same slug
                name='نام دیگر',
                field_type=FieldType.TEXT,
            )

    def test_column_with_select_options(self, table_columns):
        """Test column with select options."""
        category_column = table_columns[4]
        assert category_column.field_type == FieldType.SELECT
        assert 'options' in category_column.config
        assert len(category_column.config['options']) == 3

    def test_column_with_validation(self, table_columns):
        """Test column with validation rules."""
        price_column = table_columns[1]
        assert 'min' in price_column.validation
        assert price_column.validation['min'] == 0


@pytest.mark.django_db
class TestTableRecord:
    """Tests for TableRecord model."""

    def test_create_record(self, table_definition, user):
        """Test creating a record."""
        record = TableRecord.objects.create(
            tenant=table_definition.tenant,
            table=table_definition,
            data={'name': 'تست', 'price': 50000},
            owner=user,
        )
        assert record.id is not None
        assert record.data['name'] == 'تست'
        assert record.status == RecordStatus.DRAFT

    def test_record_str(self, table_record):
        """Test string representation."""
        assert 'محصولات' in str(table_record)

    def test_record_soft_delete(self, table_record):
        """Test soft delete functionality."""
        table_record.soft_delete()
        assert table_record.is_deleted is True
        assert table_record.deleted_at is not None

    def test_record_restore(self, table_record):
        """Test restore functionality."""
        table_record.soft_delete()
        table_record.restore()
        assert table_record.is_deleted is False
        assert table_record.deleted_at is None

    def test_record_get_value(self, table_record):
        """Test getting a value from record data."""
        assert table_record.get_value('name') == 'محصول تست'
        assert table_record.get_value('price') == 100000
        assert table_record.get_value('nonexistent', 'default') == 'default'

    def test_record_set_value(self, table_record):
        """Test setting a value in record data."""
        table_record.set_value('name', 'محصول جدید')
        assert table_record.data['name'] == 'محصول جدید'

    def test_record_version_increment(self, table_definition, table_columns, table_record):
        """Test version field increment on update via service."""
        from apps.services.worktable.services import RecordService
        
        initial_version = table_record.version
        RecordService.update_record(table_record, {'name': 'تغییر نام'})
        table_record.refresh_from_db()
        assert table_record.version == initial_version + 1


@pytest.mark.django_db
class TestSavedFilter:
    """Tests for SavedFilter model."""

    def test_create_saved_filter(self, table_definition, user):
        """Test creating a saved filter."""
        filter_obj = SavedFilter.objects.create(
            table=table_definition,
            user=user,
            name='محصولات فعال',
            filters={
                'conditions': [
                    {'field': 'is_active', 'operator': 'eq', 'value': True}
                ]
            },
        )
        assert filter_obj.id is not None
        assert filter_obj.is_default is False

    def test_saved_filter_str(self, table_definition, user):
        """Test string representation."""
        filter_obj = SavedFilter.objects.create(
            table=table_definition,
            user=user,
            name='فیلتر تست',
            filters={},
        )
        assert 'فیلتر تست' in str(filter_obj)


@pytest.mark.django_db
class TestCustomView:
    """Tests for CustomView model."""

    def test_create_custom_view(self, table_definition, user):
        """Test creating a custom view."""
        view = CustomView.objects.create(
            table=table_definition,
            user=user,
            name='نمایش ساده',
            columns=['name', 'price'],
        )
        assert view.id is not None
        assert len(view.columns) == 2

    def test_custom_view_str(self, table_definition, user):
        """Test string representation."""
        view = CustomView.objects.create(
            table=table_definition,
            user=user,
            name='نمایش تست',
            columns=['name'],
        )
        assert 'نمایش تست' in str(view)


@pytest.mark.django_db
class TestRecordAuditLog:
    """Tests for RecordAuditLog model."""

    def test_create_audit_log(self, table_definition, table_record, user):
        """Test creating an audit log entry."""
        log = RecordAuditLog.objects.create(
            table=table_definition,
            record_id=table_record.id,
            user=user,
            action=AuditAction.CREATE,
            changes={'name': {'old': None, 'new': 'محصول تست'}},
        )
        assert log.id is not None
        assert log.action == AuditAction.CREATE

    def test_audit_log_str(self, table_definition, table_record, user):
        """Test string representation."""
        log = RecordAuditLog.objects.create(
            table=table_definition,
            record_id=table_record.id,
            user=user,
            action=AuditAction.UPDATE,
            changes={},
        )
        # __str__ uses value ('update') not label ('ویرایش')
        assert AuditAction.UPDATE.value in str(log)
