# models.py for clients app

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils import timezone
from django.core.validators import MinValueValidator, MaxValueValidator, ValidationError
import uuid

class User(AbstractUser):
    #Custom user model extending Django's AbstractUser
    
    USER_TYPE_CHOICES = [
        ('admin', 'Admin'),
        ('coach', 'Coach'),
        ('player', 'Player'),
        ('journalist', 'Journalist'),
        ('general', 'General'),
    ]
    
    USER_STATE_CHOICES = [
        ('enabled', 'Enabled'),
        ('disabled', 'Disabled'),
        ('deleted', 'Deleted'),
    ]
    
    # Basic information
    user_type = models.CharField(max_length=20, choices=USER_TYPE_CHOICES)
    state = models.CharField(max_length=20, choices=USER_STATE_CHOICES, default='enabled')
    phone_number = models.CharField(max_length=20, blank=True)
    address = models.TextField(blank=True)
    logo = models.ImageField(upload_to='user_logos/', null=True, blank=True)
    
    # Cross-database references (using IDs instead of ForeignKeys)
    team_ids = models.JSONField(default=list, blank=True)  # List of team IDs from internal DB
    internal_player_id = models.IntegerField(null=True, blank=True)  # Reference to Player model in internal DB
    
    # Metadata
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    last_login_ip = models.GenericIPAddressField(null=True, blank=True)
    
    # Unique identifier for cross-database operations
    uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    
    def __str__(self):
        return f"{self.get_full_name() or self.username} ({self.get_user_type_display()})"
    
    class Meta:
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['user_type', 'state']),
            models.Index(fields=['uuid']),
        ]

class Permission(models.Model):
    """
    Plantilla de permisos para controlar QUÉ DATOS puede ver un usuario.
    Independiente del sistema de permisos de Django.
    
    Ejemplos:
    - "Ver estadísticas de un equipo"
    - "Bloquear visualización de equipo rival"
    - "Acceso solo a datos de partidos (no históricos)"
    """
    
    TYPE_CHOICES = [
        ('allow', 'Allow'),  # Permitir ver datos
        ('block', 'Block'),  # Bloquear visualización
    ]
    
    LEVEL_CHOICES = [
        ('region', 'Region'),
        ('competition', 'Competition'),
        ('team', 'Team'),
        ('division', 'Division'),
        ('match', 'Match'),
        ('player', 'Player'),
    ]
    
    DEPTH_CHOICES = [
        ('instant', 'Instant'),    # Solo datos de partidos individuales
        ('historic', 'Historic'),   # Incluye métricas históricas/agregadas
    ]
    
    # Identificación
    name = models.CharField(
        max_length=100,
        help_text="Nombre descriptivo: 'Ver Equipo', 'Bloquear Rival'"
    )
    description = models.TextField(blank=True)
    
    # Configuración del permiso
    type = models.CharField(max_length=10, choices=TYPE_CHOICES)
    level = models.CharField(max_length=20, choices=LEVEL_CHOICES)
    depth = models.CharField(max_length=10, choices=DEPTH_CHOICES)
    
    # Prioridad para resolver conflictos
    # Ejemplo: Block con prioridad 20 gana sobre Allow con prioridad 10
    priority = models.IntegerField(
        default=0,
        help_text="Mayor número = mayor prioridad en conflictos"
    )
    
    # Estado
    is_active = models.BooleanField(default=True)
    
    # Metadata
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    def __str__(self):
        return f"[{self.get_type_display()}] {self.name} (P:{self.priority})"
    
    class Meta:
        db_table = 'clients_permission'
        verbose_name = 'Data Permission Template'
        verbose_name_plural = 'Data Permission Templates'
        ordering = ['-priority', 'name']
        indexes = [
            models.Index(fields=['type', 'level']),
            models.Index(fields=['priority']),
            models.Index(fields=['is_active']),
        ]


class ClientPermission(models.Model):
    """
    Asigna un permiso de visualización a un usuario para un recurso específico.
    
    Ejemplo:
    - Usuario "juan_perez" puede ver (allow) datos del team_id=10
    - Usuario "maria_lopez" NO puede ver (block) datos del team_id=5
    
    El campo relation_id define QUÉ recurso específico:
    - Si level='team' → relation_id = {"team_id": 10}
    - Si level='match' → relation_id = {"match_id": 123}
    - Si level='player' → relation_id = {"player_id": 456}
    """
    
    STATE_CHOICES = [
        ('active', 'Active'),
        ('inactive', 'Inactive'),
        ('expired', 'Expired'),
        ('deleted', 'Deleted'),
    ]
    
    # Relaciones
    client = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='data_permissions'  # user.data_permissions.all()
    )
    permission = models.ForeignKey(
        Permission,
        on_delete=models.CASCADE,
        related_name='assignments'
    )
    
    # Contexto: A QUÉ recurso específico aplica este permiso
    relation_id = models.JSONField(
        default=dict,
        help_text='Ejemplo: {"team_ids": [10, 14]} o {"match_ids": [123]}'
    )
    
    # Timeline de DATOS: Qué rango de fechas de datos históricos puede ver
    timeline_start = models.DateField(
        help_text="Puede ver datos desde esta fecha"
    )
    timeline_end = models.DateField(
        help_text="Puede ver datos hasta esta fecha"
    )
    
    # Vigencia del PERMISO: Cuándo está activo (vinculado a suscripción)
    starts_at = models.DateTimeField(
        help_text="El permiso empieza a aplicar desde aquí"
    )
    expires_at = models.DateTimeField(
        help_text="El permiso expira aquí"
    )
    
    # Estado
    state = models.CharField(max_length=20, choices=STATE_CHOICES, default='active')
    
    # Metadata
    notes = models.TextField(
        blank=True,
        help_text="Notas administrativas sobre este permiso"
    )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='data_permissions_created'
    )

    def clean(self):
        super().clean()
        
        if not self.permission_id:
            return

        level = self.permission.level
        data = self.relation_id or {}
        
        # Definir la clave esperada según el nivel (en plural)
        key_map = {
            'team': 'team_ids',
            'competition': 'competition_ids',
            'division': 'division_ids',
            'match': 'match_ids',
            'player': 'player_ids',
            'region': 'region_ids'
        }

        expected_key = key_map.get(level)

        if expected_key:
            # 1. Validar que la clave exista
            if expected_key not in data:
                raise ValidationError(f"Para nivel '{level}', el JSON debe tener la clave '{expected_key}'.")
            
            values = data[expected_key]

            # 2. Validar que sea una lista
            if not isinstance(values, list):
                raise ValidationError(f"El valor de '{expected_key}' debe ser una lista de IDs (ej: [1, 2]).")
            
            # 3. Validar que la lista no esté vacía (opcional, pero recomendado)
            if not values:
                raise ValidationError(f"La lista '{expected_key}' no puede estar vacía.")

            # 4. Validar que todos los elementos sean enteros
            if not all(isinstance(x, int) for x in values):
                raise ValidationError(f"Todos los elementos en '{expected_key}' deben ser números enteros.")
    
    def __str__(self):
        resource = list(self.relation_id.values())[0] if self.relation_id else 'N/A'
        return f"{self.client.username} | {self.permission.name} | {self.permission.level}:{resource}"
    
    def is_valid_now(self):
        """Verifica si el permiso está vigente en este momento"""
        now = timezone.now()
        return (
            self.state == 'active' and
            self.starts_at <= now <= self.expires_at
        )
    
    class Meta:
        db_table = 'clients_clientpermission'
        verbose_name = 'Client Data Permission'
        verbose_name_plural = 'Client Data Permissions'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['client', 'state']),
            models.Index(fields=['permission', 'state']),
            models.Index(fields=['starts_at', 'expires_at']),
            models.Index(fields=['client', 'state', 'starts_at', 'expires_at']),
        ]

class SupportTicket(models.Model): # esta en clients 
    #PQR System - Petitions, Complaints, Claims and Suggestions
    
    TICKET_TYPE_CHOICES = [
        ('petition', 'Petition'),
        ('complaint', 'Complaint'),
        ('claim', 'Claim'),
        ('suggestion', 'Suggestion'),
    ]
    
    PRIORITY_CHOICES = [
        ('low', 'Low'),
        ('medium', 'Medium'),
        ('high', 'High'),
        ('urgent', 'Urgent'),
    ]
    
    STATUS_CHOICES = [
        ('open', 'Open'),
        ('in_progress', 'In Progress'),
        ('waiting_user', 'Waiting for User'),
        ('resolved', 'Resolved'),
        ('closed', 'Closed'),
    ]
    
    # Ticket information
    ticket_number = models.CharField(max_length=20, unique=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tickets')
    ticket_type = models.CharField(max_length=20, choices=TICKET_TYPE_CHOICES)
    
    # Content
    subject = models.CharField(max_length=200)
    description = models.TextField()
    
    # Status and priority
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='open')
    priority = models.CharField(max_length=20, choices=PRIORITY_CHOICES, default='medium')
    
    # Assignment
    assigned_to = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, 
                                   related_name='assigned_tickets')
    
    # Dates
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    resolved_at = models.DateTimeField(null=True, blank=True)
    closed_at = models.DateTimeField(null=True, blank=True)
    
    # SLA
    response_deadline = models.DateTimeField(null=True, blank=True)
    resolution_deadline = models.DateTimeField(null=True, blank=True)
    
    def save(self, *args, **kwargs):
        if not self.ticket_number:
            # Generate ticket number
            import random
            import string
            self.ticket_number = f"TKT-{timezone.now().strftime('%Y%m%d')}-{''.join(random.choices(string.digits, k=4))}"
        super().save(*args, **kwargs)
    
    def __str__(self):
        return f"{self.ticket_number} - {self.subject}"
    
    class Meta:
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['status', 'priority']),
            models.Index(fields=['ticket_number']),
        ]



class TicketMessage(models.Model): # esta en clients
    #Thread-style messages for support tickets
    
    ticket = models.ForeignKey(SupportTicket, on_delete=models.CASCADE, related_name='messages')
    sender = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    
    # Message content
    message = models.TextField()
    attachments = models.JSONField(default=list, blank=True)  # List of file paths
    
    # Metadata
    is_internal_note = models.BooleanField(default=False)  # Internal notes not visible to user
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return f"Message on {self.ticket.ticket_number} by {self.sender.username if self.sender else 'System'}"
    
    class Meta:
        ordering = ['created_at']



class UserActivity(models.Model): # esta en clients
    #Track user activity and interactions

    ACTIVITY_TYPE_CHOICES = [
        ('login', 'Login'),
        ('logout', 'Logout'),
        ('page_view', 'Page View'),
        ('report_generated', 'Report Generated'),
        ('report_downloaded', 'Report Downloaded'),
        ('data_export', 'Data Export'),
        ('settings_changed', 'Settings Changed'),
        ('api_call', 'API Call'),
    ]
    
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='activities')
    activity_type = models.CharField(max_length=30, choices=ACTIVITY_TYPE_CHOICES)
    
    # Activity details
    page_url = models.CharField(max_length=500, blank=True)
    ip_address = models.GenericIPAddressField(null=True, blank=True)
    user_agent = models.TextField(blank=True)
    
    # Additional context
    metadata = models.JSONField(default=dict, blank=True)
    
    #Example for report_generated:
    # {
    #     "report_type": "player_performance",
    #     "match_id": 123,
    #     "player_id": 45,
    #     "format": "pdf",
    #     "processing_time": 2.5
    # }
    
    
    # Session tracking
    session_id = models.CharField(max_length=100, blank=True)
    
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return f"{self.user.username} - {self.get_activity_type_display()} at {self.created_at}"
    
    class Meta:
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['user', 'activity_type', 'created_at']),
            models.Index(fields=['session_id']),
        ]



class UserPreference(models.Model): # esta en clients 
    # User preferences and settings
    
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='preferences')
    
    # Display preferences
    language = models.CharField(max_length=10, default='en')
    timezone = models.CharField(max_length=50, default='UTC')
    date_format = models.CharField(max_length=20, default='YYYY-MM-DD')
    
    # Notification preferences
    email_notifications = models.BooleanField(default=True)
    sms_notifications = models.BooleanField(default=False)
    notification_types = models.JSONField(default=dict, blank=True)
    # {
    #     "match_results": true,
    #     "weekly_reports": true,
    #     "payment_reminders": true,
    #     "system_updates": false
    # }
    
    # Dashboard preferences
    default_dashboard_view = models.CharField(max_length=50, default='overview')
    favorite_teams = models.JSONField(default=list, blank=True)  # List of team IDs
    favorite_players = models.JSONField(default=list, blank=True)  # List of player IDs
    
    # Data preferences
    default_date_range = models.CharField(max_length=20, default='last_30_days')
    default_chart_type = models.CharField(max_length=20, default='line')
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    def __str__(self):
        return f"Preferences for {self.user.username}"
    
    class Meta:
        verbose_name_plural = "User preferences"



class DataAccessLog(models.Model): # esta en clients
    # Log data access for security and compliance
    
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='data_access_logs')
    
    # What was accessed
    resource_type = models.CharField(max_length=50)  # e.g., 'match', 'player', 'team'
    resource_id = models.IntegerField()  # ID from internal database
    action = models.CharField(max_length=50)  # e.g., 'view', 'export', 'analyze'
    
    # Access context
    ip_address = models.GenericIPAddressField()
    access_granted = models.BooleanField(default=True)
    denial_reason = models.CharField(max_length=200, blank=True)
    
    # Performance metrics
    response_time_ms = models.IntegerField(null=True, blank=True)
    
    created_at = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return f"{self.user.username} - {self.action} {self.resource_type}:{self.resource_id}"
    
    class Meta:
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['user', 'created_at']),
            models.Index(fields=['resource_type', 'resource_id']),
        ]
