"""
File Service — Data Models.

سرویس فایل مرکزی پلتفرم.
- StoredFile: فایل فیزیکی (deduplicate شده بر اساس checksum)
- FileReference: ارجاع به فایل از context‌های مختلف (Chat, DMS, ...)
"""
import hashlib
import uuid

from django.conf import settings
from django.db import models

from apps.core.tenant.models import TenantAwareModel


# ──────────────────────────────────────────────────────────────
# Enums
# ──────────────────────────────────────────────────────────────

class StorageBackend(models.TextChoices):
    LOCAL = 'local', 'فایل‌سیستم محلی'
    S3 = 's3', 'Amazon S3'
    MINIO = 'minio', 'MinIO'


class FileStatus(models.TextChoices):
    UPLOADING = 'uploading', 'در حال آپلود'
    ACTIVE = 'active', 'فعال'
    ARCHIVED = 'archived', 'آرشیو شده'
    DELETED = 'deleted', 'حذف شده'


class ReferenceContext(models.TextChoices):
    CHAT = 'chat', 'چت'
    DMS = 'dms', 'مدیریت اسناد'
    PROJECT = 'project', 'پروژه'
    TASK = 'task', 'تسک'
    OTHER = 'other', 'سایر'


# ──────────────────────────────────────────────────────────────
# StoredFile — فایل فیزیکی (deduplicate شده)
# ──────────────────────────────────────────────────────────────

class StoredFile(TenantAwareModel):
    """
    فایل فیزیکی ذخیره‌شده در سیستم.
    هر فایل فقط یک بار ذخیره می‌شود (deduplication بر اساس checksum).
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

    # --- Metadata ---
    original_name = models.CharField('نام اصلی فایل', max_length=500)
    mime_type = models.CharField('نوع فایل', max_length=255, blank=True, default='')
    size = models.BigIntegerField('حجم (بایت)', default=0)
    extension = models.CharField('پسوند', max_length=50, blank=True, default='')

    # --- Storage ---
    storage_backend = models.CharField(
        'نوع ذخیره‌سازی',
        max_length=20,
        choices=StorageBackend.choices,
        default=StorageBackend.LOCAL,
    )
    storage_path = models.CharField(
        'مسیر ذخیره‌سازی',
        max_length=1000,
        help_text='مسیر نسبی فایل در storage',
    )
    checksum = models.CharField(
        'چک‌سام SHA-256',
        max_length=64,
        db_index=True,
        help_text='برای جلوگیری از ذخیره تکراری',
    )

    # --- Status ---
    status = models.CharField(
        'وضعیت',
        max_length=20,
        choices=FileStatus.choices,
        default=FileStatus.ACTIVE,
    )

    # --- Audit ---
    uploaded_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='uploaded_files',
        verbose_name='آپلودکننده',
    )
    reference_count = models.PositiveIntegerField(
        'تعداد ارجاع',
        default=0,
        help_text='تعداد FileReference‌های فعال',
    )

    created_at = models.DateTimeField('تاریخ ایجاد', auto_now_add=True)
    updated_at = models.DateTimeField('تاریخ بروزرسانی', auto_now=True)

    class Meta:
        db_table = 'fs_stored_file'
        verbose_name = 'فایل ذخیره‌شده'
        verbose_name_plural = 'فایل‌های ذخیره‌شده'
        ordering = ['-created_at']
        unique_together = [('tenant', 'checksum')]

    def __str__(self):
        return f"{self.original_name} ({self.size_display})"

    @property
    def size_display(self):
        """نمایش حجم خوانا."""
        if self.size < 1024:
            return f"{self.size} B"
        elif self.size < 1024 * 1024:
            return f"{self.size / 1024:.1f} KB"
        elif self.size < 1024 * 1024 * 1024:
            return f"{self.size / (1024 * 1024):.1f} MB"
        return f"{self.size / (1024 * 1024 * 1024):.1f} GB"

    @staticmethod
    def compute_checksum(file_obj) -> str:
        """محاسبه SHA-256 checksum."""
        sha256 = hashlib.sha256()
        for chunk in file_obj.chunks():
            sha256.update(chunk)
        file_obj.seek(0)
        return sha256.hexdigest()


# ──────────────────────────────────────────────────────────────
# FileReference — ارجاع از context‌های مختلف
# ──────────────────────────────────────────────────────────────

class FileReference(TenantAwareModel):
    """
    ارجاع به یک فایل از context خاص.
    یک فایل فیزیکی می‌تواند چندین ارجاع داشته باشد.
    مثال: فایلی که هم در چت و هم در DMS استفاده شده.
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

    stored_file = models.ForeignKey(
        StoredFile,
        on_delete=models.CASCADE,
        related_name='references',
        verbose_name='فایل ذخیره‌شده',
    )

    # --- Context (generic reference) ---
    context = models.CharField(
        'نوع context',
        max_length=20,
        choices=ReferenceContext.choices,
    )
    context_id = models.UUIDField(
        'شناسه context',
        db_index=True,
        help_text='شناسه رکورد مرتبط (پیام چت، سند DMS، ...)',
    )

    # --- Display ---
    display_name = models.CharField(
        'نام نمایشی',
        max_length=500,
        blank=True,
        default='',
        help_text='نام نمایشی در context (می‌تواند با نام اصلی فرق کند)',
    )

    # --- Audit ---
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='file_references',
        verbose_name='ایجادکننده',
    )
    is_active = models.BooleanField('فعال', default=True)

    created_at = models.DateTimeField('تاریخ ایجاد', auto_now_add=True)

    class Meta:
        db_table = 'fs_file_reference'
        verbose_name = 'ارجاع فایل'
        verbose_name_plural = 'ارجاع‌های فایل'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['context', 'context_id']),
        ]

    def __str__(self):
        name = self.display_name or self.stored_file.original_name
        return f"{name} → {self.context}:{self.context_id}"
