"""
Worktable Service Models.

This module contains all models for the Worktable service including:
- TableDefinition: Schema definition for dynamic tables
- TableColumn: Column definitions with field types
- TableRecord: Dynamic records stored as JSONB
- SavedFilter: User-saved filter configurations
- CustomView: Custom column arrangements and display settings
- RecordAuditLog: Change history tracking
"""
import uuid

from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _

from apps.core.tenant.models import TenantAwareModel


class FieldType(models.TextChoices):
    """Supported field types for table columns."""
    TEXT = 'text', _('متن')
    TEXTAREA = 'textarea', _('متن چندخطی')
    NUMBER = 'number', _('عدد صحیح')
    DECIMAL = 'decimal', _('عدد اعشاری')
    DATE = 'date', _('تاریخ')
    DATETIME = 'datetime', _('تاریخ و زمان')
    BOOLEAN = 'boolean', _('بله/خیر')
    SELECT = 'select', _('انتخاب از لیست')
    MULTISELECT = 'multiselect', _('انتخاب چندگانه')
    RELATION = 'relation', _('ارتباط')
    FILE = 'file', _('فایل')
    IMAGE = 'image', _('تصویر')
    EMAIL = 'email', _('ایمیل')
    URL = 'url', _('آدرس وب')
    PHONE = 'phone', _('تلفن')
    JSON = 'json', _('داده JSON')
    COMPUTED = 'computed', _('محاسباتی')


class RecordStatus(models.TextChoices):
    """Status options for table records."""
    DRAFT = 'draft', _('پیش‌نویس')
    PENDING = 'pending', _('در انتظار تأیید')
    APPROVED = 'approved', _('تأیید شده')
    REJECTED = 'rejected', _('رد شده')
    ARCHIVED = 'archived', _('بایگانی شده')


class AuditAction(models.TextChoices):
    """Audit log action types."""
    CREATE = 'create', _('ایجاد')
    UPDATE = 'update', _('ویرایش')
    DELETE = 'delete', _('حذف')
    RESTORE = 'restore', _('بازیابی')
    BULK_CREATE = 'bulk_create', _('ایجاد دسته‌ای')
    BULK_UPDATE = 'bulk_update', _('ویرایش دسته‌ای')
    BULK_DELETE = 'bulk_delete', _('حذف دسته‌ای')
    STATUS_CHANGE = 'status_change', _('تغییر وضعیت')
    EXPORT = 'export', _('خروجی')
    IMPORT = 'import', _('ورودی')


class TableDefinition(TenantAwareModel):
    """
    Defines the schema and settings for a dynamic table.
    
    Each table belongs to a tenant and contains multiple columns
    that define the structure of records.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False
    )
    slug = models.SlugField(
        max_length=100,
        verbose_name=_('شناسه'),
        help_text=_('شناسه یکتا برای URL')
    )
    name = models.CharField(
        max_length=255,
        verbose_name=_('نام'),
        help_text=_('نام نمایشی جدول')
    )
    description = models.TextField(
        blank=True,
        null=True,
        verbose_name=_('توضیحات')
    )
    icon = models.CharField(
        max_length=50,
        blank=True,
        null=True,
        verbose_name=_('آیکون'),
        help_text=_('نام آیکون (مثلاً package, users)')
    )
    settings = models.JSONField(
        default=dict,
        blank=True,
        verbose_name=_('تنظیمات'),
        help_text=_('تنظیمات جدول شامل allow_export, page_size و ...')
    )
    is_active = models.BooleanField(
        default=True,
        verbose_name=_('فعال')
    )
    enable_audit = models.BooleanField(
        default=True,
        verbose_name=_('ثبت تاریخچه'),
        help_text=_('فعال بودن ثبت تغییرات')
    )
    enable_workflow = models.BooleanField(
        default=False,
        verbose_name=_('Workflow'),
        help_text=_('فعال بودن گردش کار')
    )
    order = models.PositiveIntegerField(
        default=0,
        verbose_name=_('ترتیب')
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name=_('تاریخ ایجاد')
    )
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name=_('تاریخ بروزرسانی')
    )

    class Meta:
        db_table = 'worktable_table_definition'
        verbose_name = _('تعریف جدول')
        verbose_name_plural = _('تعریف جداول')
        unique_together = ['tenant', 'slug']
        ordering = ['order', 'name']

    def __str__(self):
        return self.name

    def get_default_settings(self):
        """Return default settings merged with custom settings."""
        defaults = {
            'allow_export': True,
            'allow_import': True,
            'allow_bulk_delete': True,
            'allow_inline_edit': True,
            'page_size': 20,
            'default_sort': {'field': 'created_at', 'order': 'desc'}
        }
        return {**defaults, **self.settings}

    @property
    def column_count(self):
        """Return the number of columns in this table."""
        return self.columns.count()

    @property
    def record_count(self):
        """Return the number of active records in this table."""
        return self.records.filter(is_deleted=False).count()


class TableColumn(models.Model):
    """
    Defines a column (field) in a dynamic table.
    
    Each column has a type, validation rules, and display settings.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False
    )
    table = models.ForeignKey(
        TableDefinition,
        on_delete=models.CASCADE,
        related_name='columns',
        verbose_name=_('جدول')
    )
    slug = models.SlugField(
        max_length=100,
        verbose_name=_('شناسه'),
        help_text=_('شناسه فیلد در داده')
    )
    name = models.CharField(
        max_length=255,
        verbose_name=_('نام'),
        help_text=_('نام نمایشی ستون')
    )
    field_type = models.CharField(
        max_length=50,
        choices=FieldType.choices,
        default=FieldType.TEXT,
        verbose_name=_('نوع فیلد')
    )
    config = models.JSONField(
        default=dict,
        blank=True,
        verbose_name=_('تنظیمات'),
        help_text=_('تنظیمات خاص نوع فیلد')
    )
    validation = models.JSONField(
        default=dict,
        blank=True,
        verbose_name=_('اعتبارسنجی'),
        help_text=_('قوانین اعتبارسنجی')
    )
    is_required = models.BooleanField(
        default=False,
        verbose_name=_('الزامی')
    )
    is_unique = models.BooleanField(
        default=False,
        verbose_name=_('یکتا')
    )
    is_sortable = models.BooleanField(
        default=True,
        verbose_name=_('قابل مرتب‌سازی')
    )
    is_filterable = models.BooleanField(
        default=True,
        verbose_name=_('قابل فیلتر')
    )
    is_searchable = models.BooleanField(
        default=False,
        verbose_name=_('قابل جستجو')
    )
    is_visible = models.BooleanField(
        default=True,
        verbose_name=_('نمایش در لیست')
    )
    default_value = models.TextField(
        blank=True,
        null=True,
        verbose_name=_('مقدار پیش‌فرض')
    )
    # Relation fields
    related_table = models.ForeignKey(
        TableDefinition,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='referencing_columns',
        verbose_name=_('جدول مرتبط')
    )
    related_display_field = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        verbose_name=_('فیلد نمایش'),
        help_text=_('فیلدی که در relation نمایش داده می‌شود')
    )
    # Field-level permissions
    visible_to_roles = models.JSONField(
        default=list,
        blank=True,
        verbose_name=_('نمایش برای نقش‌ها'),
        help_text=_('خالی = همه می‌بینند')
    )
    editable_by_roles = models.JSONField(
        default=list,
        blank=True,
        verbose_name=_('ویرایش توسط نقش‌ها'),
        help_text=_('خالی = همه می‌توانند ویرایش کنند')
    )
    order = models.PositiveIntegerField(
        default=0,
        verbose_name=_('ترتیب')
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name=_('تاریخ ایجاد')
    )
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name=_('تاریخ بروزرسانی')
    )

    class Meta:
        db_table = 'worktable_table_column'
        verbose_name = _('ستون جدول')
        verbose_name_plural = _('ستون‌های جدول')
        unique_together = ['table', 'slug']
        ordering = ['order', 'name']

    def __str__(self):
        return f"{self.table.name}.{self.name}"


class TableRecord(TenantAwareModel):
    """
    A record (row) in a dynamic table.
    
    Data is stored as JSONB for flexibility.
    Includes soft delete and optimistic locking.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False
    )
    table = models.ForeignKey(
        TableDefinition,
        on_delete=models.CASCADE,
        related_name='records',
        verbose_name=_('جدول')
    )
    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        related_name='worktable_records',
        verbose_name=_('ایجادکننده')
    )
    data = models.JSONField(
        default=dict,
        verbose_name=_('داده‌ها')
    )
    status = models.CharField(
        max_length=50,
        choices=RecordStatus.choices,
        default=RecordStatus.DRAFT,
        verbose_name=_('وضعیت')
    )
    workflow_state = models.JSONField(
        null=True,
        blank=True,
        verbose_name=_('وضعیت workflow')
    )
    version = models.PositiveIntegerField(
        default=1,
        verbose_name=_('نسخه'),
        help_text=_('برای optimistic locking')
    )
    is_deleted = models.BooleanField(
        default=False,
        verbose_name=_('حذف شده'),
        db_index=True
    )
    deleted_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name=_('تاریخ حذف')
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name=_('تاریخ ایجاد')
    )
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name=_('تاریخ بروزرسانی')
    )

    class Meta:
        db_table = 'worktable_table_record'
        verbose_name = _('رکورد')
        verbose_name_plural = _('رکوردها')
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['table', 'is_deleted']),
            models.Index(fields=['owner']),
            models.Index(fields=['status']),
            models.Index(fields=['created_at']),
        ]

    def __str__(self):
        return f"{self.table.name} - {self.id}"

    def get_value(self, field_slug, default=None):
        """Get a value from the record's data by field slug."""
        return self.data.get(field_slug, default)

    def set_value(self, field_slug, value):
        """Set a value in the record's data by field slug."""
        self.data[field_slug] = value

    def soft_delete(self):
        """Soft delete the record."""
        from django.utils import timezone
        self.is_deleted = True
        self.deleted_at = timezone.now()
        self.save(update_fields=['is_deleted', 'deleted_at', 'updated_at'])

    def restore(self):
        """Restore a soft-deleted record."""
        self.is_deleted = False
        self.deleted_at = None
        self.save(update_fields=['is_deleted', 'deleted_at', 'updated_at'])

    def save(self, *args, **kwargs):
        """Override save."""
        super().save(*args, **kwargs)


class SavedFilter(models.Model):
    """
    User-saved filter configurations for a table.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False
    )
    table = models.ForeignKey(
        TableDefinition,
        on_delete=models.CASCADE,
        related_name='saved_filters',
        verbose_name=_('جدول')
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='worktable_filters',
        verbose_name=_('کاربر')
    )
    name = models.CharField(
        max_length=255,
        verbose_name=_('نام')
    )
    filters = models.JSONField(
        default=dict,
        verbose_name=_('فیلترها')
    )
    is_default = models.BooleanField(
        default=False,
        verbose_name=_('پیش‌فرض')
    )
    is_shared = models.BooleanField(
        default=False,
        verbose_name=_('عمومی')
    )
    order = models.PositiveIntegerField(
        default=0,
        verbose_name=_('ترتیب')
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name=_('تاریخ ایجاد')
    )

    class Meta:
        db_table = 'worktable_saved_filter'
        verbose_name = _('فیلتر ذخیره شده')
        verbose_name_plural = _('فیلترهای ذخیره شده')
        ordering = ['order', 'name']

    def __str__(self):
        return f"{self.table.name} - {self.name}"


class CustomView(models.Model):
    """
    Custom column arrangements and display settings for a table.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False
    )
    table = models.ForeignKey(
        TableDefinition,
        on_delete=models.CASCADE,
        related_name='custom_views',
        verbose_name=_('جدول')
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='worktable_views',
        verbose_name=_('کاربر')
    )
    name = models.CharField(
        max_length=255,
        verbose_name=_('نام')
    )
    columns = models.JSONField(
        default=list,
        verbose_name=_('ستون‌ها'),
        help_text=_('لیست ستون‌ها با تنظیمات width و visible')
    )
    sort = models.JSONField(
        default=list,
        blank=True,
        verbose_name=_('مرتب‌سازی')
    )
    filters = models.JSONField(
        default=dict,
        blank=True,
        verbose_name=_('فیلترها')
    )
    is_default = models.BooleanField(
        default=False,
        verbose_name=_('پیش‌فرض')
    )
    is_shared = models.BooleanField(
        default=False,
        verbose_name=_('عمومی')
    )
    order = models.PositiveIntegerField(
        default=0,
        verbose_name=_('ترتیب')
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name=_('تاریخ ایجاد')
    )

    class Meta:
        db_table = 'worktable_custom_view'
        verbose_name = _('نمایش سفارشی')
        verbose_name_plural = _('نمایش‌های سفارشی')
        ordering = ['order', 'name']

    def __str__(self):
        return f"{self.table.name} - {self.name}"


class RecordAuditLog(models.Model):
    """
    Audit log for tracking changes to records.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False
    )
    table = models.ForeignKey(
        TableDefinition,
        on_delete=models.CASCADE,
        related_name='audit_logs',
        verbose_name=_('جدول')
    )
    record_id = models.UUIDField(
        verbose_name=_('شناسه رکورد'),
        db_index=True,
        help_text=_('نگهداری حتی بعد از حذف رکورد')
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        related_name='worktable_audit_logs',
        verbose_name=_('کاربر')
    )
    action = models.CharField(
        max_length=50,
        choices=AuditAction.choices,
        verbose_name=_('عملیات')
    )
    changes = models.JSONField(
        default=dict,
        verbose_name=_('تغییرات'),
        help_text=_('فرمت: {field: {old, new}}')
    )
    metadata = models.JSONField(
        default=dict,
        blank=True,
        verbose_name=_('متادیتا')
    )
    ip_address = models.GenericIPAddressField(
        null=True,
        blank=True,
        verbose_name=_('آدرس IP')
    )
    user_agent = models.TextField(
        blank=True,
        null=True,
        verbose_name=_('User Agent')
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name=_('تاریخ'),
        db_index=True
    )

    class Meta:
        db_table = 'worktable_record_audit_log'
        verbose_name = _('لاگ تغییرات')
        verbose_name_plural = _('لاگ‌های تغییرات')
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['table', 'record_id']),
            models.Index(fields=['user']),
        ]

    def __str__(self):
        return f"{self.action} - {self.record_id}"
