"""
Document Control Service Models.

This module contains all models for the Document Control service including:
- DocumentCategory: Hierarchical categorization of documents
- Document: Core document entity with metadata and status
- DocumentVersion: Version history with file tracking
- DocumentApproval: Approval workflow records
- DocumentAccess: Access control per document
- DocumentAuditLog: Audit trail for all document actions
"""
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


# ──────────────────────────────────────────────────────────────
# Enums
# ──────────────────────────────────────────────────────────────

class DocumentStatus(models.TextChoices):
    """Status lifecycle of a document."""
    DRAFT = 'draft', _('پیش‌نویس')
    PENDING_REVIEW = 'pending_review', _('در انتظار بررسی')
    APPROVED = 'approved', _('تأیید شده')
    REJECTED = 'rejected', _('رد شده')
    OBSOLETE = 'obsolete', _('منسوخ')
    ARCHIVED = 'archived', _('بایگانی شده')


class ApprovalStatus(models.TextChoices):
    """Status of an approval request."""
    PENDING = 'pending', _('در انتظار')
    APPROVED = 'approved', _('تأیید شده')
    REJECTED = 'rejected', _('رد شده')
    CANCELLED = 'cancelled', _('لغو شده')


class AccessLevel(models.TextChoices):
    """Permission level for document access."""
    VIEW = 'view', _('مشاهده')
    EDIT = 'edit', _('ویرایش')
    APPROVE = 'approve', _('تأیید')
    ADMIN = 'admin', _('مدیر')


class DocumentAccessType(models.TextChoices):
    """Type of access assignment — user or role."""
    USER = 'user', _('کاربر')
    ROLE = 'role', _('نقش')


class AuditAction(models.TextChoices):
    """Audit log action types for documents."""
    CREATE = 'create', _('ایجاد')
    UPDATE = 'update', _('ویرایش')
    DELETE = 'delete', _('حذف')
    VIEW = 'view', _('مشاهده')
    CHECKOUT = 'checkout', _('تحویل گرفتن')
    CHECKIN = 'checkin', _('تحویل دادن')
    PUBLISH = 'publish', _('انتشار')
    ARCHIVE = 'archive', _('بایگانی')
    APPROVE = 'approve', _('تأیید')
    REJECT = 'reject', _('رد')
    VERSION_CREATE = 'version_create', _('ایجاد نسخه')
    ACCESS_GRANT = 'access_grant', _('اعطای دسترسی')
    ACCESS_REVOKE = 'access_revoke', _('سلب دسترسی')


# ──────────────────────────────────────────────────────────────
# Models
# ──────────────────────────────────────────────────────────────

class DocumentCategory(TenantAwareModel):
    """
    Hierarchical categorization of documents.

    Supports tree structure via self-referential parent FK.
    Each category has a unique code within its tenant.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )
    name = models.CharField(
        max_length=255,
        verbose_name=_('نام دسته'),
    )
    code = models.CharField(
        max_length=50,
        verbose_name=_('کد دسته'),
    )
    parent = models.ForeignKey(
        'self',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='children',
        verbose_name=_('دسته والد'),
    )
    description = models.TextField(
        blank=True,
        default='',
        verbose_name=_('توضیحات'),
    )
    sort_order = models.IntegerField(
        default=0,
        verbose_name=_('ترتیب نمایش'),
    )
    is_active = models.BooleanField(
        default=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 = 'dc_document_category'
        verbose_name = _('دسته اسناد')
        verbose_name_plural = _('دسته‌های اسناد')
        ordering = ['sort_order', 'name']
        unique_together = [('tenant', 'code')]

    def __str__(self):
        return f'{self.code} - {self.name}'


class Document(TenantAwareModel):
    """
    Core document entity with metadata, status, and versioning.

    Documents go through a lifecycle: DRAFT → PENDING_REVIEW → APPROVED → OBSOLETE/ARCHIVED.
    Supports checkout/checkin workflow for controlled editing.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )
    title = models.CharField(
        max_length=500,
        verbose_name=_('عنوان'),
    )
    code = models.CharField(
        max_length=100,
        verbose_name=_('کد سند'),
        help_text=_('شناسه یکتا سند در سازمان'),
    )
    category = models.ForeignKey(
        DocumentCategory,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='documents',
        verbose_name=_('دسته'),
    )
    description = models.TextField(
        blank=True,
        default='',
        verbose_name=_('توضیحات'),
    )
    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='owned_documents',
        verbose_name=_('مالک'),
    )
    status = models.CharField(
        max_length=20,
        choices=DocumentStatus.choices,
        default=DocumentStatus.DRAFT,
        db_index=True,
        verbose_name=_('وضعیت'),
    )
    current_version = models.PositiveIntegerField(
        default=0,
        verbose_name=_('نسخه فعلی'),
    )
    metadata = models.JSONField(
        default=dict,
        blank=True,
        verbose_name=_('متادیتا'),
        help_text=_('اطلاعات اضافی سند'),
    )
    access_level = models.CharField(
        max_length=20,
        choices=AccessLevel.choices,
        default=AccessLevel.VIEW,
        verbose_name=_('سطح دسترسی پیش‌فرض'),
    )
    is_checked_out = models.BooleanField(
        default=False,
        verbose_name=_('تحویل گرفته شده'),
    )
    checked_out_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='checked_out_documents',
        verbose_name=_('تحویل‌گیرنده'),
    )
    checked_out_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name=_('زمان تحویل'),
    )
    # Soft delete
    is_deleted = models.BooleanField(default=False, db_index=True)
    deleted_at = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('تاریخ ایجاد'))
    updated_at = models.DateTimeField(auto_now=True, verbose_name=_('تاریخ بروزرسانی'))

    class Meta:
        db_table = 'dc_document'
        verbose_name = _('سند')
        verbose_name_plural = _('اسناد')
        ordering = ['-created_at']
        unique_together = [('tenant', 'code')]

    def __str__(self):
        return f'{self.code} - {self.title}'


class DocumentVersion(TenantAwareModel):
    """
    Tracks each version of a document with file information.

    Each version stores the file URL, size, MIME type, and a description of changes.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )
    document = models.ForeignKey(
        Document,
        on_delete=models.CASCADE,
        related_name='versions',
        verbose_name=_('سند'),
    )
    version_number = models.PositiveIntegerField(
        verbose_name=_('شماره نسخه'),
    )
    file_url = models.CharField(
        max_length=1000,
        verbose_name=_('آدرس فایل'),
    )
    file_name = models.CharField(
        max_length=500,
        verbose_name=_('نام فایل'),
    )
    file_size = models.BigIntegerField(
        default=0,
        verbose_name=_('حجم فایل (بایت)'),
    )
    mime_type = models.CharField(
        max_length=100,
        blank=True,
        default='',
        verbose_name=_('نوع فایل'),
    )
    change_description = models.TextField(
        blank=True,
        default='',
        verbose_name=_('شرح تغییرات'),
    )
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='document_versions',
        verbose_name=_('ایجادکننده'),
    )
    is_current = models.BooleanField(
        default=False,
        db_index=True,
        verbose_name=_('نسخه فعلی'),
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('تاریخ ایجاد'))

    class Meta:
        db_table = 'dc_document_version'
        verbose_name = _('نسخه سند')
        verbose_name_plural = _('نسخه‌های سند')
        ordering = ['-version_number']
        unique_together = [('document', 'version_number')]

    def __str__(self):
        return f'{self.document.code} v{self.version_number}'


class DocumentApproval(TenantAwareModel):
    """
    Records approval workflow for document versions.

    Tracks who approved/rejected, when, and their comments.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )
    document = models.ForeignKey(
        Document,
        on_delete=models.CASCADE,
        related_name='approvals',
        verbose_name=_('سند'),
    )
    version = models.ForeignKey(
        DocumentVersion,
        on_delete=models.CASCADE,
        related_name='approvals',
        verbose_name=_('نسخه'),
    )
    approver = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='document_approvals',
        verbose_name=_('تأییدکننده'),
    )
    status = models.CharField(
        max_length=20,
        choices=ApprovalStatus.choices,
        default=ApprovalStatus.PENDING,
        db_index=True,
        verbose_name=_('وضعیت'),
    )
    comments = models.TextField(
        blank=True,
        default='',
        verbose_name=_('نظرات'),
    )
    approved_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 = 'dc_document_approval'
        verbose_name = _('تأیید سند')
        verbose_name_plural = _('تأییدات سند')
        ordering = ['-created_at']

    def __str__(self):
        return f'Approval: {self.document.code} v{self.version.version_number} - {self.status}'


class DocumentAccess(TenantAwareModel):
    """
    Access control per document — grants user or role specific permission level.

    Supports both user-level and role-level access assignments.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )
    document = models.ForeignKey(
        Document,
        on_delete=models.CASCADE,
        related_name='access_rules',
        verbose_name=_('سند'),
    )
    access_type = models.CharField(
        max_length=10,
        choices=DocumentAccessType.choices,
        default=DocumentAccessType.USER,
        verbose_name=_('نوع دسترسی'),
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='document_access_rules',
        verbose_name=_('کاربر'),
    )
    role_id = models.UUIDField(
        null=True,
        blank=True,
        verbose_name=_('شناسه نقش'),
        help_text=_('UUID نقش از سرویس دسترسی'),
    )
    permission_level = models.CharField(
        max_length=20,
        choices=AccessLevel.choices,
        default=AccessLevel.VIEW,
        verbose_name=_('سطح دسترسی'),
    )
    granted_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='granted_document_access',
        verbose_name=_('اعطاکننده'),
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('تاریخ ایجاد'))

    class Meta:
        db_table = 'dc_document_access'
        verbose_name = _('دسترسی سند')
        verbose_name_plural = _('دسترسی‌های سند')
        ordering = ['-created_at']

    def __str__(self):
        target = self.user or f'Role: {self.role_id}'
        return f'{self.document.code} → {target} ({self.permission_level})'


class DocumentAuditLog(TenantAwareModel):
    """
    Audit trail for all document actions.

    Records who did what, when, and from where.
    """
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )
    document = models.ForeignKey(
        Document,
        on_delete=models.CASCADE,
        related_name='audit_logs',
        verbose_name=_('سند'),
    )
    action = models.CharField(
        max_length=20,
        choices=AuditAction.choices,
        verbose_name=_('عملیات'),
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='document_audit_logs',
        verbose_name=_('کاربر'),
    )
    details = models.JSONField(
        default=dict,
        blank=True,
        verbose_name=_('جزئیات'),
    )
    ip_address = models.GenericIPAddressField(
        null=True,
        blank=True,
        verbose_name=_('آدرس IP'),
    )
    user_agent = models.CharField(
        max_length=500,
        blank=True,
        default='',
        verbose_name=_('User Agent'),
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('تاریخ ایجاد'))

    class Meta:
        db_table = 'dc_document_audit_log'
        verbose_name = _('لاگ بازرسی سند')
        verbose_name_plural = _('لاگ‌های بازرسی اسناد')
        ordering = ['-created_at']

    def __str__(self):
        return f'{self.document.code} - {self.action} by {self.user}'
