"""
Channel Relationship Models

This module contains models that define relationships between channels
and other entities, particularly zone-specific configurations.

Models:
    - ChannelZoneRelation: Through model for Channel-Zone relationships
"""

from django.db import models
from django.utils.translation import gettext_lazy as _

from apps.common.models import BaseModel
from apps.channels.models.channels import Channel, ChannelZone, ChannelCodec 


class ChannelZoneRelation(BaseModel):
    """
    Through model for Channel-Zone Many-to-Many relationship.
    
    Contains zone-specific configuration for each channel, including
    custom streaming URLs, codec overrides, VPN settings, and FTP configurations.
    This allows channels to have different technical configurations
    for different geographic zones.
    
    Attributes:
        channel (Channel): The channel this configuration applies to
        zone (ChannelZone): The zone this configuration is for
        codec (ChannelCodec): Zone-specific codec override
        stream_url (str): Zone-specific streaming URL
        is_active (bool): Whether channel is active in this zone
        priority (int): Priority level for this zone configuration
        
    VPN Configuration:
        vpn_type (str): Type of VPN connection
        vpn_server_address (str): VPN server address
        vpn_username/password (str): VPN credentials
        
    IPSec Configuration:
        ipsec_preshared_key (str): IPSec pre-shared key
        ipsec_local_subnet/remote_subnet (str): Network subnets
        
    OpenVPN Configuration:
        openvpn_config_file (FileField): Configuration file
        openvpn_ca_cert/client_cert/client_key (str): Certificates
        
    WireGuard Configuration:
        wireguard_private_key/public_key (str): Cryptographic keys
        wireguard_endpoint (str): Server endpoint
        wireguard_allowed_ips (str): Allowed IP ranges
        
    FTP Configuration:
        ftp_host/username/password (str): FTP server details
        ftp_port (int): FTP server port
        ftp_root_directory (str): Root directory path
        ftp_use_passive (bool): Passive mode setting
        
    Relationships:
        - channel: Many-to-one with Channel
        - zone: Many-to-one with ChannelZone  
        - codec: Many-to-one with ChannelCodec (optional)
        
    Example:
        >>> relation = ChannelZoneRelation.objects.create(
        ...     channel=my_channel,
        ...     zone=europe_zone,
        ...     stream_url="https://eu-stream.example.com/channel1",
        ...     vpn_type="openvpn",
        ...     priority=10
        ... )
    """
    
    VPN_TYPES = [
        ('none', _('No VPN')),
        ('ipsec', _('IPSec Tunnel')),
        ('openvpn', _('OpenVPN')),
        ('wireguard', _('WireGuard')),
    ]
    
    # Core Relationship
    channel = models.ForeignKey(
        Channel,
        on_delete=models.CASCADE,
        related_name='zone_relations',
        verbose_name=_('Channel'),
        help_text=_('The channel this configuration applies to')
    )
    zone = models.ForeignKey(
        ChannelZone,
        on_delete=models.CASCADE,
        related_name='channel_relations',
        verbose_name=_('Zone'),
        help_text=_('The geographic zone this configuration is for')
    )
    
    # Zone-specific Technical Configuration
    codec = models.ForeignKey(
        ChannelCodec,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='zone_relations',
        verbose_name=_('Zone-specific Codec'),
        help_text=_('Override codec configuration for this zone')
    )

    # Stream URL Configuration
    stream_url = models.URLField(
        blank=True,
        verbose_name=_('Zone-specific Stream URL'),
        help_text=_('Custom streaming URL for this zone')
    )
    backup_stream_url = models.URLField(
        blank=True,
        verbose_name=_('Zone-specific Backup Stream URL'),
        help_text=_('Secondary URL for failover streaming')
    )

    # Channel Region FTP Attribute
    ftp_zone_name = models.CharField(
        max_length=255,
        blank=True,
        verbose_name=_('Zone Name'),
        help_text=_('Name of the zone for FTP configuration example: 2005, 2008, 2010, etc')
    )
    ftp_verife_number = models.CharField(
        max_length=255,
        blank=True,
        verbose_name=_('Verification Number'),
        help_text=_('Verification number for FTP configuration example: 00001, 00002, etc')
    )
    ftp_platform_name = models.CharField(
        max_length=255,
        blank=True,
        verbose_name=_('Platform Name'),
        help_text=_('Name of the platform for FTP configuration example: CJI, TDF, 2M, etc')
    )

    # Optional reference to standalone configurations
    standalone_vpn_config = models.ForeignKey(
        'StandaloneVPNConfiguration',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='channel_zone_relations',
        verbose_name=_('Standalone VPN Configuration'),
        help_text=_('Reference to a standalone VPN configuration (overrides inline VPN settings)')
    )
    standalone_ftp_config = models.ForeignKey(
        'StandaloneFTPConfiguration',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='channel_zone_relations',
        verbose_name=_('Standalone FTP Configuration'),
        help_text=_('Reference to a standalone FTP configuration (overrides inline FTP settings)')
    )
    
    # Legacy FTP Configuration for Content Delivery (kept for backward compatibility)
    ftp_host = models.CharField(
        max_length=255,
        blank=True,
        verbose_name=_('FTP Host'),
        help_text=_('FTP server hostname or IP address for content delivery (legacy - use standalone config instead)')
    )
    ftp_username = models.CharField(
        max_length=100,
        blank=True,
        verbose_name=_('FTP Username'),
        help_text=_('Username for FTP authentication')
    )
    ftp_password = models.CharField(
        max_length=255,
        blank=True,
        verbose_name=_('FTP Password'),
        help_text=_('Password for FTP authentication')
    )
    ftp_port = models.PositiveIntegerField(
        default=21,
        verbose_name=_('FTP Port'),
        help_text=_('FTP server port number (default: 21)')
    )
    ftp_root_directory = models.CharField(
        max_length=500,
        blank=True,
        default="/",
        verbose_name=_('FTP Root Directory'),
        help_text=_('Root directory path on the FTP server')
    )
    ftp_use_passive = models.BooleanField(
        default=True,
        verbose_name=_('Use FTP Passive Mode'),
        help_text=_('Whether to use passive mode for FTP connections')
    )
    
    # VPN Configuration Base
    vpn_type = models.CharField(
        max_length=20,
        choices=VPN_TYPES,
        default='none',
        verbose_name=_('VPN Type'),
        help_text=_('Type of VPN connection for secure streaming')
    )
    vpn_server_address = models.CharField(
        max_length=255,
        blank=True,
        verbose_name=_('VPN Server Address'),
        help_text=_('VPN server IP address or hostname')
    )
    vpn_username = models.CharField(
        max_length=100,
        blank=True,
        verbose_name=_('VPN Username'),
        help_text=_('Username for VPN authentication')
    )
    vpn_password = models.CharField(
        max_length=255,
        blank=True,
        verbose_name=_('VPN Password'),
        help_text=_('Password for VPN authentication')
    )

    # Connection Management
    is_active = models.BooleanField(
        default=True,
        verbose_name=_('Active in Zone'),
        help_text=_('Whether this channel is active in this zone')
    )
    priority = models.PositiveIntegerField(
        default=1,
        verbose_name=_('Priority'),
        help_text=_('Priority level for this zone (higher number = higher priority)')
    )
    
    class Meta:
        db_table = "channel_zone_relations"
        unique_together = ['channel', 'zone']
        ordering = ['channel', 'zone', '-priority']
        verbose_name = _('Channel Zone Relation')
        verbose_name_plural = _('Channel Zone Relations')
        indexes = [
            models.Index(fields=['channel', 'zone']),
            models.Index(fields=['zone', 'is_active']),
            models.Index(fields=['channel', 'is_active', 'priority']),
        ]
    
    def __str__(self):
        return f"{self.channel.name} in {self.zone.name}"

    def get_effective_stream_url(self):
        """
        Get the effective stream URL, falling back to channel default.
        
        Returns:
            str: Stream URL to use for this zone
        """
        return self.stream_url or self.backup_stream_url
    
    def get_effective_codec(self):
        """
        Get the effective codec, falling back to channel default.
        
        Returns:
            ChannelCodec: Codec configuration to use for this zone
        """
        return self.codec 

    def get_connection_info(self):
        """
        Get comprehensive connection information for this zone.
        
        Returns:
            dict: Connection information including stream, FTP, and VPN details
        """
        return {
            'stream_url': self.stream_url,
            'ftp': {
                'host': self.ftp_host,
                'username': self.ftp_username,
                'password': self.ftp_password,
                'port': self.ftp_port,
                'root_directory': self.ftp_root_directory,
                'use_passive': self.ftp_use_passive,
            },
            'vpn': {
                'type': self.vpn_type,
                'server_address': self.vpn_server_address,
                'username': self.vpn_username,
                'password': self.vpn_password,
            }
        }
    
    def get_active_vpn_configuration(self):
        """
        Get the active VPN configuration, prioritizing standalone config over inline config.
        Returns the appropriate VPN configuration object or None.
        """
        # First check for standalone configuration
        if self.standalone_vpn_config:
            return self.standalone_vpn_config
            
        # Fall back to legacy inline configurations
        if self.vpn_type == 'ipsec' and hasattr(self, 'ipsecconfig_config'):
            return self.ipsecconfig_config
        elif self.vpn_type == 'openvpn' and hasattr(self, 'openvpnconfig_config'):
            return self.openvpnconfig_config
        elif self.vpn_type == 'wireguard' and hasattr(self, 'wireguardconfig_config'):
            return self.wireguardconfig_config
        return None
    
    def get_active_ftp_configuration(self):
        """
        Get the active FTP configuration, prioritizing standalone config over inline config.
        Returns a dict with FTP configuration or None.
        """
        # First check for standalone configuration
        if self.standalone_ftp_config:
            return {
                'host': self.standalone_ftp_config.host,
                'username': self.standalone_ftp_config.username,
                'password': self.standalone_ftp_config.password,
                'port': self.standalone_ftp_config.port,
                'root_directory': self.standalone_ftp_config.root_directory,
                'passive_mode': self.standalone_ftp_config.passive_mode,
                'ssl_enabled': self.standalone_ftp_config.ssl_enabled,
                'timeout': self.standalone_ftp_config.timeout,
            }
            
        # Fall back to legacy inline configuration
        if self.ftp_host:
            return {
                'host': self.ftp_host,
                'username': self.ftp_username,
                'password': self.ftp_password,
                'port': self.ftp_port,
                'root_directory': self.ftp_root_directory,
                'passive_mode': self.ftp_use_passive,
                'ssl_enabled': False,  # Legacy doesn't have SSL
                'timeout': 30,  # Default timeout
            }
        return None
    
    def has_ftp_configuration(self):
        """
        Check if FTP configuration is complete.
        
        Returns:
            bool: True if all required FTP fields are configured
        """
        return bool(self.ftp_host and self.ftp_username)
