# Generated by Django 4.2.13 on 2025-08-12 10:30

import apps.channels.utils
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import uuid


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='Channel',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('name', models.CharField(help_text='Full official name of the television channel', max_length=200, verbose_name='Channel Name')),
                ('display_name', models.CharField(help_text='Official call sign or short identifier (e.g., "WABC-TV", "ESPN")', max_length=20, unique=True, verbose_name='Call Sign')),
                ('channel_number', models.CharField(help_text='Channel number in cable/satellite listings (e.g., "7.1", "ESPN")', max_length=20, verbose_name='Channel Number')),
                ('channel_type', models.CharField(choices=[('terrestrial', 'Terrestrial/Over-the-Air'), ('cable', 'Cable Channel'), ('satellite', 'Satellite Channel'), ('iptv', 'IPTV Channel'), ('streaming', 'Streaming Channel'), ('radio', 'Radio Station')], default='satellite', help_text='Broadcasting technology and distribution method', max_length=20, verbose_name='Channel Type')),
                ('status', models.CharField(choices=[('active', 'Active'), ('inactive', 'Inactive'), ('maintenance', 'Maintenance'), ('testing', 'Testing')], default='active', help_text='Current operational status of the channel', max_length=20, verbose_name='Channel Status')),
                ('logo', models.ImageField(blank=True, help_text='Channel logo or branding image', null=True, upload_to='channels/logos/', verbose_name='Channel Logo')),
                ('description', models.TextField(blank=True, help_text='Brief description of the channel and its content', verbose_name='Channel Description')),
                ('website', models.URLField(blank=True, help_text="Channel's official website URL", verbose_name='Official Website')),
                ('language', models.CharField(blank=True, help_text='Primary language of broadcast content', max_length=250, verbose_name='Primary Language')),
                ('category', models.CharField(blank=True, help_text='Primary content category (News, Sports, Entertainment, etc.)', max_length=250, verbose_name='Content Category')),
                ('target_audience', models.CharField(blank=True, help_text='Primary target demographic (Children, Adults, Seniors, etc.)', max_length=100, verbose_name='Target Audience')),
                ('supports_dai', models.BooleanField(default=True, help_text='Whether the channel supports Dynamic Ad Insertion', verbose_name='Supports DAI')),
                ('last_health_check', models.DateTimeField(blank=True, help_text='Timestamp of the most recent health monitoring check', null=True, verbose_name='Last Health Check')),
                ('is_online', models.BooleanField(default=True, help_text='Current online/offline status of the channel', verbose_name='Is Online')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name': 'Channel',
                'verbose_name_plural': 'Channels',
                'db_table': 'channels',
                'ordering': ['channel_number', 'name'],
            },
        ),
        migrations.CreateModel(
            name='ChannelCodec',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('name', models.CharField(help_text='Human-readable name for this codec configuration', max_length=100, verbose_name='Codec Name')),
                ('video_codec', models.CharField(help_text='Video codec identifier (h264, h265, vp9, etc.)', max_length=50, verbose_name='Video Codec')),
                ('audio_codec', models.CharField(help_text='Audio codec identifier (aac, mp3, opus, etc.)', max_length=50, verbose_name='Audio Codec')),
                ('resolution', models.CharField(blank=True, help_text='Video resolution in WIDTHxHEIGHT format (e.g., 1920x1080)', max_length=20, verbose_name='Resolution')),
                ('bitrate', models.PositiveIntegerField(help_text='Target bitrate in kbps', verbose_name='Bitrate')),
                ('frame_rate', models.DecimalField(blank=True, decimal_places=2, help_text='Target frame rate in fps (e.g., 29.97, 25.00)', max_digits=5, null=True, verbose_name='Frame Rate')),
                ('ffmpeg_options', models.JSONField(blank=True, default=dict, help_text='Additional FFmpeg encoding options as JSON object', verbose_name='FFmpeg Options')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name': 'Channel Codec',
                'verbose_name_plural': 'Channel Codecs',
                'db_table': 'channel_codecs',
                'ordering': ['name'],
            },
        ),
        migrations.CreateModel(
            name='ChannelZone',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('name', models.CharField(help_text='Human-readable name of the geographic zone', max_length=255, verbose_name='Zone Name')),
                ('code', models.CharField(help_text='Unique identifier code for the zone (e.g., "NAE", "EUR")', max_length=10, unique=True, verbose_name='Zone Code')),
                ('description', models.TextField(blank=True, help_text='Optional detailed description of the zone coverage', verbose_name='Description')),
                ('timezone', models.CharField(default='UTC', help_text='Timezone identifier (e.g., "America/New_York", "Europe/London")', max_length=50, verbose_name='Timezone')),
                ('is_active', models.BooleanField(default=True, help_text='Whether this zone is currently accepting broadcasts', verbose_name='Is Active')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name': 'Channel Zone',
                'verbose_name_plural': 'Channel Zones',
                'db_table': 'channel_zones',
                'ordering': ['name'],
            },
        ),
        migrations.CreateModel(
            name='ChannelZoneRelation',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('stream_url', models.URLField(blank=True, help_text='Custom streaming URL for this zone', verbose_name='Zone-specific Stream URL')),
                ('backup_stream_url', models.URLField(blank=True, help_text='Secondary URL for failover streaming', verbose_name='Zone-specific Backup Stream URL')),
                ('ftp_zone_name', models.CharField(blank=True, help_text='Name of the zone for FTP configuration example: 2005, 2008, 2010, etc', max_length=255, verbose_name='Zone Name')),
                ('ftp_verife_number', models.CharField(blank=True, help_text='Verification number for FTP configuration example: 00001, 00002, etc', max_length=255, verbose_name='Verification Number')),
                ('ftp_platform_name', models.CharField(blank=True, help_text='Name of the platform for FTP configuration example: CJI, TDF, 2M, etc', max_length=255, verbose_name='Platform Name')),
                ('ftp_host', models.CharField(blank=True, help_text='FTP server hostname or IP address for content delivery (legacy - use standalone config instead)', max_length=255, verbose_name='FTP Host')),
                ('ftp_username', models.CharField(blank=True, help_text='Username for FTP authentication', max_length=100, verbose_name='FTP Username')),
                ('ftp_password', models.CharField(blank=True, help_text='Password for FTP authentication', max_length=255, verbose_name='FTP Password')),
                ('ftp_port', models.PositiveIntegerField(default=21, help_text='FTP server port number (default: 21)', verbose_name='FTP Port')),
                ('ftp_root_directory', models.CharField(blank=True, default='/', help_text='Root directory path on the FTP server', max_length=500, verbose_name='FTP Root Directory')),
                ('ftp_use_passive', models.BooleanField(default=True, help_text='Whether to use passive mode for FTP connections', verbose_name='Use FTP Passive Mode')),
                ('vpn_type', models.CharField(choices=[('none', 'No VPN'), ('ipsec', 'IPSec Tunnel'), ('openvpn', 'OpenVPN'), ('wireguard', 'WireGuard')], default='none', help_text='Type of VPN connection for secure streaming', max_length=20, verbose_name='VPN Type')),
                ('vpn_server_address', models.CharField(blank=True, help_text='VPN server IP address or hostname', max_length=255, verbose_name='VPN Server Address')),
                ('vpn_username', models.CharField(blank=True, help_text='Username for VPN authentication', max_length=100, verbose_name='VPN Username')),
                ('vpn_password', models.CharField(blank=True, help_text='Password for VPN authentication', max_length=255, verbose_name='VPN Password')),
                ('is_active', models.BooleanField(default=True, help_text='Whether this channel is active in this zone', verbose_name='Active in Zone')),
                ('priority', models.PositiveIntegerField(default=1, help_text='Priority level for this zone (higher number = higher priority)', verbose_name='Priority')),
                ('channel', models.ForeignKey(help_text='The channel this configuration applies to', on_delete=django.db.models.deletion.CASCADE, related_name='zone_relations', to='channels.channel', verbose_name='Channel')),
                ('codec', models.ForeignKey(blank=True, help_text='Override codec configuration for this zone', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='zone_relations', to='channels.channelcodec', verbose_name='Zone-specific Codec')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
            ],
            options={
                'verbose_name': 'Channel Zone Relation',
                'verbose_name_plural': 'Channel Zone Relations',
                'db_table': 'channel_zone_relations',
                'ordering': ['channel', 'zone', '-priority'],
            },
        ),
        migrations.CreateModel(
            name='Jingle',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('name', models.CharField(help_text='Human-readable name for this jingle', max_length=255, verbose_name='Jingle Name')),
                ('jingle_type', models.CharField(choices=[('station_id', 'Station ID'), ('bumper', 'Bumper'), ('promo', 'Promo'), ('transition', 'Transition'), ('commercial_break', 'Commercial Break'), ('news_intro', 'News Intro'), ('weather_intro', 'Weather Intro'), ('sports_intro', 'Sports Intro'), ('music_intro', 'Music Intro'), ('show_opener', 'Show Opener'), ('show_closer', 'Show Closer')], db_index=True, help_text='Type of jingle content', max_length=20, verbose_name='Jingle Type')),
                ('placement_type', models.CharField(choices=[('start', 'Start of Show'), ('end', 'End of Show'), ('commercial_start', 'Start of Commercial Break'), ('commercial_end', 'End of Commercial Break'), ('program_transition', 'Program Transition'), ('segment_transition', 'Segment Transition'), ('hourly', 'Hourly'), ('half_hourly', 'Half Hourly'), ('quarter_hourly', 'Quarter Hourly'), ('top_of_hour', 'Top of Hour'), ('bottom_of_hour', 'Bottom of Hour'), ('random', 'Random Placement'), ('manual', 'Manual Only')], db_index=True, default='random', help_text='When this jingle should be played in the broadcast', max_length=20, verbose_name='Placement Type')),
                ('priority', models.PositiveSmallIntegerField(choices=[(1, 'Very Low'), (2, 'Low'), (3, 'Normal'), (4, 'High'), (5, 'Very High'), (6, 'Critical')], default=3, help_text='Priority level for jingle selection (higher number = higher priority)', verbose_name='Priority Level')),
                ('file', models.FileField(help_text='Audio file for this jingle (automatically organized by channel and date)', upload_to=apps.channels.utils.jingle_upload_path, verbose_name='Audio File')),
                ('md5_file', models.FileField(blank=True, help_text='MD5 checksum file (automatically generated after audio upload)', null=True, upload_to=apps.channels.utils.md5_upload_path, verbose_name='MD5 Checksum File')),
                ('duration', models.PositiveIntegerField(blank=True, help_text='Duration of the jingle in seconds', null=True, verbose_name='Duration (seconds)')),
                ('file_size', models.PositiveBigIntegerField(blank=True, help_text='Size of the audio file in bytes', null=True, verbose_name='File Size (bytes)')),
                ('metadata', models.JSONField(blank=True, default=dict, help_text='Additional audio metadata (bitrate, sample rate, channels, etc.)', verbose_name='Audio Metadata')),
                ('audio_fingerprint', models.TextField(blank=True, help_text='Audio fingerprint data for automatic detection in streams', verbose_name='Audio Fingerprint')),
                ('frames_fingerprint', models.TextField(blank=True, help_text='Frames fingerprint data for automatic detection in streams', verbose_name='Frames Fingerprint')),
                ('is_active', models.BooleanField(default=True, help_text='Whether this jingle is currently active', verbose_name='Is Active')),
                ('start_date', models.DateField(blank=True, help_text='Optional start date for when this jingle becomes active', null=True, verbose_name='Start Date')),
                ('end_date', models.DateField(blank=True, help_text='Optional end date for when this jingle becomes inactive', null=True, verbose_name='End Date')),
                ('time_slots', models.JSONField(blank=True, default=list, help_text='JSON list of time ranges when this jingle can play', verbose_name='Time Slots')),
                ('play_count', models.PositiveIntegerField(default=0, help_text='Number of times this jingle has been played', verbose_name='Play Count')),
                ('last_played', models.DateTimeField(blank=True, help_text='Timestamp of when this jingle was last played', null=True, verbose_name='Last Played')),
                ('channel', models.ForeignKey(help_text='Channel this jingle belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='jingles', to='channels.channel', verbose_name='Channel')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name': 'Jingle',
                'verbose_name_plural': 'Jingles',
                'db_table': 'jingles',
                'ordering': ['channel', '-created_at', 'name'],
            },
        ),
        migrations.CreateModel(
            name='StandaloneFTPConfiguration',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('name', models.CharField(help_text='Human-readable name for this FTP configuration', max_length=255, verbose_name='Configuration Name')),
                ('description', models.TextField(blank=True, help_text='Optional description of this FTP configuration', verbose_name='Description')),
                ('host', models.CharField(help_text='FTP server hostname or IP address', max_length=255, verbose_name='FTP Host')),
                ('username', models.CharField(help_text='Username for FTP authentication', max_length=100, verbose_name='Username')),
                ('password', models.CharField(help_text='Password for FTP authentication', max_length=255, verbose_name='Password')),
                ('port', models.PositiveIntegerField(default=21, help_text='FTP server port number (default: 21)', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65535)], verbose_name='Port')),
                ('root_directory', models.CharField(default='/', help_text='Root directory path on the FTP server', max_length=500, verbose_name='Root Directory')),
                ('passive_mode', models.BooleanField(default=True, help_text='Whether to use passive mode for FTP connections', verbose_name='Passive Mode')),
                ('ssl_enabled', models.BooleanField(default=False, help_text='Whether to use FTPS (FTP over SSL/TLS)', verbose_name='SSL/TLS Enabled')),
                ('timeout', models.PositiveIntegerField(default=30, help_text='Connection timeout in seconds', validators=[django.core.validators.MinValueValidator(5), django.core.validators.MaxValueValidator(300)], verbose_name='Timeout')),
                ('zone_name', models.CharField(blank=True, help_text='Zone identifier for FTP configuration (e.g., 2005, 2008)', max_length=255, verbose_name='Zone Name')),
                ('verification_number', models.CharField(blank=True, help_text='Verification number for FTP configuration (e.g., 00001, 00002)', max_length=255, verbose_name='Verification Number')),
                ('platform_name', models.CharField(blank=True, help_text='Platform identifier (e.g., CJI, TDF, 2M)', max_length=255, verbose_name='Platform Name')),
                ('is_active', models.BooleanField(default=True, help_text='Whether this FTP configuration is active', verbose_name='Is Active')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name': 'Standalone FTP Configuration',
                'verbose_name_plural': 'Standalone FTP Configurations',
                'db_table': 'standalone_ftp_configurations',
                'ordering': ['name'],
            },
        ),
        migrations.CreateModel(
            name='StandaloneVPNConfiguration',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('name', models.CharField(help_text='Human-readable name for this VPN configuration', max_length=255, verbose_name='Configuration Name')),
                ('description', models.TextField(blank=True, help_text='Optional description of this VPN configuration', verbose_name='Description')),
                ('vpn_type', models.CharField(choices=[('ipsec', 'IPSec Tunnel'), ('openvpn', 'OpenVPN'), ('wireguard', 'WireGuard')], help_text='Type of VPN technology to use', max_length=20, verbose_name='VPN Type')),
                ('server_address', models.CharField(help_text='VPN server IP address or hostname', max_length=255, verbose_name='Server Address')),
                ('username', models.CharField(blank=True, help_text='Username for VPN authentication', max_length=100, verbose_name='Username')),
                ('password', models.CharField(blank=True, help_text='Password for VPN authentication', max_length=255, verbose_name='Password')),
                ('ipsec_preshared_key', models.TextField(blank=True, help_text='Pre-shared key for IPSec authentication', verbose_name='IPSec Pre-shared Key')),
                ('ipsec_local_subnet', models.CharField(blank=True, help_text='Local network subnet in CIDR notation', max_length=18, validators=[django.core.validators.RegexValidator(message='Enter a valid subnet in CIDR notation (e.g., 192.168.1.0/24)', regex='^(\\d{1,3}\\.){3}\\d{1,3}/\\d{1,2}$')], verbose_name='Local Subnet')),
                ('ipsec_remote_subnet', models.CharField(blank=True, help_text='Remote network subnet in CIDR notation', max_length=18, validators=[django.core.validators.RegexValidator(message='Enter a valid subnet in CIDR notation (e.g., 10.0.0.0/24)', regex='^(\\d{1,3}\\.){3}\\d{1,3}/\\d{1,2}$')], verbose_name='Remote Subnet')),
                ('ipsec_encryption_algorithm', models.CharField(blank=True, choices=[('aes128', 'AES-128'), ('aes192', 'AES-192'), ('aes256', 'AES-256'), ('3des', '3DES')], help_text='Encryption algorithm for IPSec tunnel', max_length=20, verbose_name='Encryption Algorithm')),
                ('openvpn_config_file', models.FileField(blank=True, help_text='OpenVPN configuration file (.ovpn)', null=True, upload_to='vpn/openvpn/configs/', verbose_name='OpenVPN Config File')),
                ('openvpn_ca_cert', models.TextField(blank=True, help_text='Certificate Authority certificate content', verbose_name='CA Certificate')),
                ('openvpn_client_cert', models.TextField(blank=True, help_text='Client certificate content', verbose_name='Client Certificate')),
                ('openvpn_client_key', models.TextField(blank=True, help_text='Client private key content', verbose_name='Client Private Key')),
                ('openvpn_compression', models.BooleanField(default=False, help_text='Whether to enable LZO compression', verbose_name='Enable Compression')),
                ('wireguard_private_key', models.CharField(blank=True, help_text='WireGuard private key (base64 encoded)', max_length=44, verbose_name='Private Key')),
                ('wireguard_public_key', models.CharField(blank=True, help_text='WireGuard public key (base64 encoded)', max_length=44, verbose_name='Public Key')),
                ('wireguard_peer_public_key', models.CharField(blank=True, help_text='WireGuard peer public key (base64 encoded)', max_length=44, verbose_name='Peer Public Key')),
                ('wireguard_endpoint', models.CharField(blank=True, help_text='WireGuard endpoint (IP:port or hostname:port)', max_length=255, verbose_name='Endpoint')),
                ('wireguard_allowed_ips', models.TextField(blank=True, help_text='Comma-separated list of allowed IP ranges', verbose_name='Allowed IPs')),
                ('wireguard_persistent_keepalive', models.PositiveIntegerField(blank=True, help_text='Keepalive interval in seconds (optional)', null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65535)], verbose_name='Persistent Keepalive')),
                ('is_active', models.BooleanField(default=True, help_text='Whether this VPN configuration is active', verbose_name='Is Active')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name': 'Standalone VPN Configuration',
                'verbose_name_plural': 'Standalone VPN Configurations',
                'db_table': 'standalone_vpn_configurations',
                'ordering': ['name'],
            },
        ),
        migrations.CreateModel(
            name='WireGuardConfiguration',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('is_enabled', models.BooleanField(default=True, help_text='Whether this VPN configuration is currently enabled', verbose_name='Is Enabled')),
                ('private_key', models.TextField(help_text='WireGuard private key for this client', verbose_name='Private Key')),
                ('public_key', models.TextField(blank=True, help_text='WireGuard public key for this client (auto-generated from private key)', verbose_name='Public Key')),
                ('peer_public_key', models.TextField(help_text='WireGuard public key of the VPN server', verbose_name='Peer Public Key')),
                ('endpoint', models.CharField(help_text='WireGuard server endpoint (host:port, e.g., vpn.example.com:51820)', max_length=255, verbose_name='Endpoint')),
                ('allowed_ips', models.TextField(default='0.0.0.0/0', help_text='Comma-separated list of allowed IP ranges (CIDR notation)', verbose_name='Allowed IPs')),
                ('persistent_keepalive', models.PositiveIntegerField(default=25, help_text='Keepalive interval in seconds (0 to disable)', verbose_name='Persistent Keepalive')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
                ('zone_relation', models.OneToOneField(help_text='The zone relation this VPN configuration applies to', on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_config', to='channels.channelzonerelation', verbose_name='Zone Relation')),
            ],
            options={
                'verbose_name': 'WireGuard Configuration',
                'verbose_name_plural': 'WireGuard Configurations',
                'db_table': 'wireguard_configurations',
            },
        ),
        migrations.CreateModel(
            name='OpenVPNConfiguration',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('is_enabled', models.BooleanField(default=True, help_text='Whether this VPN configuration is currently enabled', verbose_name='Is Enabled')),
                ('config_file', models.FileField(blank=True, help_text='OpenVPN configuration file (.ovpn)', null=True, upload_to='vpn_configs/openvpn/', verbose_name='OpenVPN Config File')),
                ('ca_cert', models.TextField(blank=True, help_text='Certificate Authority certificate in PEM format', verbose_name='CA Certificate')),
                ('client_cert', models.TextField(blank=True, help_text='Client certificate in PEM format', verbose_name='Client Certificate')),
                ('client_key', models.TextField(blank=True, help_text='Client private key in PEM format', verbose_name='Client Private Key')),
                ('compression', models.CharField(choices=[('none', 'No Compression'), ('lzo', 'LZO Compression'), ('lz4', 'LZ4 Compression')], default='lzo', help_text='Compression algorithm for OpenVPN tunnel', max_length=20, verbose_name='Compression')),
                ('cipher', models.CharField(choices=[('aes-256-cbc', 'AES-256-CBC'), ('aes-192-cbc', 'AES-192-CBC'), ('aes-128-cbc', 'AES-128-CBC'), ('aes-256-gcm', 'AES-256-GCM'), ('chacha20-poly1305', 'ChaCha20-Poly1305')], default='aes-256-cbc', help_text='Encryption cipher for OpenVPN tunnel', max_length=30, verbose_name='Cipher')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
                ('zone_relation', models.OneToOneField(help_text='The zone relation this VPN configuration applies to', on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_config', to='channels.channelzonerelation', verbose_name='Zone Relation')),
            ],
            options={
                'verbose_name': 'OpenVPN Configuration',
                'verbose_name_plural': 'OpenVPN Configurations',
                'db_table': 'openvpn_configurations',
            },
        ),
        migrations.CreateModel(
            name='JingleDetection',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('detected_at', models.DateTimeField(auto_now_add=True, help_text='When the detection was recorded in the system', verbose_name='Detected At')),
                ('start_timestamp', models.DateTimeField(help_text='When the jingle started playing in the stream', verbose_name='Start Time')),
                ('end_timestamp', models.DateTimeField(help_text='When the jingle ended playing in the stream', verbose_name='End Time')),
                ('confidence_score', models.DecimalField(decimal_places=4, help_text='Detection confidence score from 0.0 to 1.0', max_digits=5, verbose_name='Confidence Score')),
                ('detection_method', models.CharField(choices=[('audio_fingerprint', 'Audio Fingerprint'), ('frames_fingerprint', 'I-Frame Fingerprint'), ('combined', 'Combined Audio/Frame'), ('manual', 'Manual Detection')], default='audio_fingerprint', help_text='Method used for detection', max_length=50, verbose_name='Detection Method')),
                ('stream_position', models.PositiveIntegerField(help_text='Position in stream where jingle was detected (seconds from start)', verbose_name='Stream Position')),
                ('status', models.CharField(choices=[('detected', 'Detected'), ('confirmed', 'Confirmed'), ('false_positive', 'False Positive')], default='detected', help_text='Validation status of this detection', max_length=20, verbose_name='Status')),
                ('metadata', models.JSONField(blank=True, default=dict, help_text='Additional detection metadata and parameters', verbose_name='Metadata')),
                ('channel', models.ForeignKey(help_text='Channel where the jingle was detected', on_delete=django.db.models.deletion.CASCADE, related_name='jingle_detections', to='channels.channel', verbose_name='Channel')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('jingle', models.ForeignKey(help_text='The jingle that was detected', on_delete=django.db.models.deletion.CASCADE, related_name='detections', to='channels.jingle', verbose_name='Jingle')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name': 'Jingle Detection',
                'verbose_name_plural': 'Jingle Detections',
                'db_table': 'jingle_detections',
                'ordering': ['-detected_at'],
            },
        ),
        migrations.CreateModel(
            name='IPSecConfiguration',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('is_enabled', models.BooleanField(default=True, help_text='Whether this VPN configuration is currently enabled', verbose_name='Is Enabled')),
                ('preshared_key', models.TextField(help_text='IPSec pre-shared key for authentication', verbose_name='Pre-shared Key')),
                ('local_subnet', models.CharField(help_text='Local network subnet in CIDR notation (e.g., 192.168.1.0/24)', max_length=18, validators=[django.core.validators.RegexValidator(message='Enter a valid CIDR subnet (e.g., 192.168.1.0/24)', regex='^(\\d{1,3}\\.){3}\\d{1,3}/\\d{1,2}$')], verbose_name='Local Subnet')),
                ('remote_subnet', models.CharField(help_text='Remote network subnet in CIDR notation (e.g., 10.0.0.0/24)', max_length=18, validators=[django.core.validators.RegexValidator(message='Enter a valid CIDR subnet (e.g., 10.0.0.0/24)', regex='^(\\d{1,3}\\.){3}\\d{1,3}/\\d{1,2}$')], verbose_name='Remote Subnet')),
                ('encryption_algorithm', models.CharField(choices=[('aes128', 'AES-128'), ('aes192', 'AES-192'), ('aes256', 'AES-256'), ('3des', '3DES')], default='aes256', help_text='Encryption algorithm for IPSec tunnel', max_length=20, verbose_name='Encryption Algorithm')),
                ('hash_algorithm', models.CharField(choices=[('sha1', 'SHA-1'), ('sha256', 'SHA-256'), ('sha384', 'SHA-384'), ('sha512', 'SHA-512'), ('md5', 'MD5')], default='sha256', help_text='Hash algorithm for integrity verification', max_length=20, verbose_name='Hash Algorithm')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
                ('zone_relation', models.OneToOneField(help_text='The zone relation this VPN configuration applies to', on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_config', to='channels.channelzonerelation', verbose_name='Zone Relation')),
            ],
            options={
                'verbose_name': 'IPSec Configuration',
                'verbose_name_plural': 'IPSec Configurations',
                'db_table': 'ipsec_configurations',
            },
        ),
        migrations.CreateModel(
            name='EPGProgram',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('title', models.CharField(help_text='Full title of the program', max_length=255, verbose_name='Program Title')),
                ('description', models.TextField(blank=True, help_text='Detailed description of the program content', verbose_name='Program Description')),
                ('program_type', models.CharField(choices=[('movie', 'Movie'), ('series', 'TV Series'), ('news', 'News'), ('sports', 'Sports'), ('documentary', 'Documentary'), ('entertainment', 'Entertainment'), ('kids', 'Kids'), ('music', 'Music'), ('other', 'Other')], default='other', help_text='Category classification of the program', max_length=20, verbose_name='Program Type')),
                ('start_time', models.DateTimeField(help_text='When the program starts broadcasting', verbose_name='Start Time')),
                ('end_time', models.DateTimeField(help_text='When the program ends broadcasting', verbose_name='End Time')),
                ('duration', models.PositiveIntegerField(help_text='Program duration in minutes', verbose_name='Duration')),
                ('season_number', models.PositiveIntegerField(blank=True, help_text='Season number for series content', null=True, verbose_name='Season Number')),
                ('episode_number', models.PositiveIntegerField(blank=True, help_text='Episode number within the season', null=True, verbose_name='Episode Number')),
                ('original_air_date', models.DateField(blank=True, help_text='Original broadcast date of this content', null=True, verbose_name='Original Air Date')),
                ('content_rating', models.CharField(blank=True, help_text='Age/content rating (G, PG, PG-13, R, etc.)', max_length=10, verbose_name='Content Rating')),
                ('language', models.CharField(blank=True, help_text='Primary language of the program', max_length=50, verbose_name='Language')),
                ('subtitles_available', models.BooleanField(default=False, help_text='Whether closed captions/subtitles are available', verbose_name='Subtitles Available')),
                ('has_ad_breaks', models.BooleanField(default=True, help_text='Whether this program supports commercial breaks', verbose_name='Has Ad Breaks')),
                ('ad_break_positions', models.JSONField(blank=True, default=list, help_text='List of timestamps (in seconds) where ads can be inserted', verbose_name='Ad Break Positions')),
                ('channel', models.ForeignKey(help_text='Channel broadcasting this program', on_delete=django.db.models.deletion.CASCADE, related_name='programs', to='channels.channel', verbose_name='Channel')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name': 'EPG Program',
                'verbose_name_plural': 'EPG Programs',
                'db_table': 'epg_programs',
                'ordering': ['channel', 'start_time'],
            },
        ),
        migrations.AddField(
            model_name='channelzonerelation',
            name='standalone_ftp_config',
            field=models.ForeignKey(blank=True, help_text='Reference to a standalone FTP configuration (overrides inline FTP settings)', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='channel_zone_relations', to='channels.standaloneftpconfiguration', verbose_name='Standalone FTP Configuration'),
        ),
        migrations.AddField(
            model_name='channelzonerelation',
            name='standalone_vpn_config',
            field=models.ForeignKey(blank=True, help_text='Reference to a standalone VPN configuration (overrides inline VPN settings)', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='channel_zone_relations', to='channels.standalonevpnconfiguration', verbose_name='Standalone VPN Configuration'),
        ),
        migrations.AddField(
            model_name='channelzonerelation',
            name='updated_by',
            field=models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By'),
        ),
        migrations.AddField(
            model_name='channelzonerelation',
            name='zone',
            field=models.ForeignKey(help_text='The geographic zone this configuration is for', on_delete=django.db.models.deletion.CASCADE, related_name='channel_relations', to='channels.channelzone', verbose_name='Zone'),
        ),
        migrations.CreateModel(
            name='ChannelSchedule',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('title', models.CharField(help_text='Title or name for this schedule entry', max_length=255, verbose_name='Schedule Title')),
                ('schedule_type', models.CharField(choices=[('regular', 'Regular Programming'), ('special', 'Special Event'), ('maintenance', 'Maintenance'), ('test', 'Test Broadcast'), ('emergency', 'Emergency Broadcast'), ('replay', 'Replay/Rerun')], default='regular', help_text='Type of scheduled content or event', max_length=20, verbose_name='Schedule Type')),
                ('start_time', models.DateTimeField(help_text='When this schedule entry begins', verbose_name='Start Time')),
                ('end_time', models.DateTimeField(help_text='When this schedule entry ends', verbose_name='End Time')),
                ('description', models.TextField(blank=True, help_text='Detailed description of the scheduled content', verbose_name='Description')),
                ('content_url', models.URLField(blank=True, help_text='Primary URL for the scheduled content stream', verbose_name='Content URL')),
                ('backup_content_url', models.URLField(blank=True, help_text='Backup URL for content streaming', verbose_name='Backup Content URL')),
                ('allow_ads', models.BooleanField(default=True, help_text='Whether ads can be inserted during this schedule', verbose_name='Allow Advertisements')),
                ('ad_break_duration', models.PositiveIntegerField(default=120, help_text='Duration of advertisement breaks in seconds', verbose_name='Ad Break Duration')),
                ('is_active', models.BooleanField(default=True, help_text='Whether this schedule entry is currently active', verbose_name='Active')),
                ('priority', models.PositiveIntegerField(default=1, help_text='Schedule priority (higher number = higher priority)', verbose_name='Priority')),
                ('notify_before_minutes', models.PositiveIntegerField(default=30, help_text='Minutes before start time to send notifications', verbose_name='Notification Lead Time')),
                ('channel', models.ForeignKey(help_text='Channel for this schedule entry', on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='channels.channel', verbose_name='Channel')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name': 'Channel Schedule',
                'verbose_name_plural': 'Channel Schedules',
                'db_table': 'channel_schedules',
                'ordering': ['channel', 'start_time', '-priority'],
            },
        ),
        migrations.AddField(
            model_name='channel',
            name='zones',
            field=models.ManyToManyField(blank=True, help_text='Geographic zones where this channel is available (can be added later during editing)', related_name='channels', through='channels.ChannelZoneRelation', to='channels.channelzone', verbose_name='Broadcasting Zones'),
        ),
        migrations.CreateModel(
            name='Adbreak',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('date', models.DateField(help_text='The date of the ad-break.', verbose_name='Date')),
                ('start_at', models.TimeField(blank=True, help_text='The start time of the ad break.', null=True, verbose_name='Ad Break Start Time')),
                ('end_at', models.TimeField(blank=True, help_text='The end time of the ad break.', null=True, verbose_name='Ad Break End Time')),
                ('duration', models.DurationField(blank=True, help_text='The duration of the ad break.', null=True, verbose_name='Duration')),
                ('adbreak_type', models.CharField(blank=True, choices=[('Pre', 'Pre'), ('Post', 'Post'), ('Mid', 'Mid')], max_length=255, null=True)),
                ('adbreak_category', models.CharField(blank=True, choices=[('History', 'History'), ('Predicted', 'Predicted'), ('RealTime', 'Realtime'), ('Conductor', 'Conductor')], max_length=255, null=True)),
                ('show_before', models.CharField(blank=True, help_text='The show before the ad break.', max_length=255, null=True, verbose_name='Show Before')),
                ('show_after', models.CharField(blank=True, help_text='The show after the ad break.', max_length=255, null=True, verbose_name='Show After')),
                ('if_show_during', models.BooleanField(default=True, help_text='Boolean indicating if the ad break is shown during a show.', verbose_name='Show During')),
                ('channel', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='channels.channel')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
            ],
            options={
                'verbose_name_plural': 'Conductor Data',
                'db_table': 'Adbreaks',
            },
        ),
        migrations.CreateModel(
            name='ZoneVPNConfiguration',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('is_default', models.BooleanField(default=False, help_text='Whether this is the default VPN configuration for the zone', verbose_name='Is Default')),
                ('priority', models.PositiveIntegerField(default=1, help_text='Priority level (higher number = higher priority)', verbose_name='Priority')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
                ('vpn_config', models.ForeignKey(help_text='The VPN configuration to use for this zone', on_delete=django.db.models.deletion.CASCADE, related_name='zone_assignments', to='channels.standalonevpnconfiguration', verbose_name='VPN Configuration')),
                ('zone', models.ForeignKey(help_text='The zone this VPN configuration applies to', on_delete=django.db.models.deletion.CASCADE, related_name='vpn_configurations', to='channels.channelzone', verbose_name='Zone')),
            ],
            options={
                'verbose_name': 'Zone VPN Configuration',
                'verbose_name_plural': 'Zone VPN Configurations',
                'db_table': 'zone_vpn_configurations',
                'ordering': ['-priority', 'zone__name'],
                'indexes': [models.Index(fields=['zone', 'is_default'], name='zone_vpn_co_zone_id_0b15de_idx'), models.Index(fields=['priority'], name='zone_vpn_co_priorit_2efb32_idx')],
                'unique_together': {('zone', 'vpn_config')},
            },
        ),
        migrations.CreateModel(
            name='ZoneFTPConfiguration',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Timestamp when this object was created', verbose_name='Created At')),
                ('updated_at', models.DateTimeField(auto_now=True, help_text='Timestamp when this object was last modified', verbose_name='Updated At')),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='Unique identifier for this object', primary_key=True, serialize=False)),
                ('is_deleted', models.BooleanField(default=False, help_text='Whether this object has been soft-deleted', verbose_name='Is Deleted')),
                ('deleted_at', models.DateTimeField(blank=True, help_text='Timestamp when this object was soft-deleted', null=True, verbose_name='Deleted At')),
                ('is_default', models.BooleanField(default=False, help_text='Whether this is the default FTP configuration for the zone', verbose_name='Is Default')),
                ('priority', models.PositiveIntegerField(default=1, help_text='Priority level (higher number = higher priority)', verbose_name='Priority')),
                ('created_by', models.ForeignKey(blank=True, help_text='User who created this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_created', to=settings.AUTH_USER_MODEL, verbose_name='Created By')),
                ('deleted_by', models.ForeignKey(blank=True, help_text='User who soft-deleted this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_deleted', to=settings.AUTH_USER_MODEL, verbose_name='Deleted By')),
                ('ftp_config', models.ForeignKey(help_text='The FTP configuration to use for this zone', on_delete=django.db.models.deletion.CASCADE, related_name='zone_assignments', to='channels.standaloneftpconfiguration', verbose_name='FTP Configuration')),
                ('updated_by', models.ForeignKey(blank=True, help_text='User who last modified this object', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(class)s_updated', to=settings.AUTH_USER_MODEL, verbose_name='Updated By')),
                ('zone', models.ForeignKey(help_text='The zone this FTP configuration applies to', on_delete=django.db.models.deletion.CASCADE, related_name='ftp_configurations', to='channels.channelzone', verbose_name='Zone')),
            ],
            options={
                'verbose_name': 'Zone FTP Configuration',
                'verbose_name_plural': 'Zone FTP Configurations',
                'db_table': 'zone_ftp_configurations',
                'ordering': ['-priority', 'zone__name'],
                'indexes': [models.Index(fields=['zone', 'is_default'], name='zone_ftp_co_zone_id_f0cc55_idx'), models.Index(fields=['priority'], name='zone_ftp_co_priorit_c3639e_idx')],
                'unique_together': {('zone', 'ftp_config')},
            },
        ),
        migrations.AddIndex(
            model_name='standalonevpnconfiguration',
            index=models.Index(fields=['vpn_type', 'is_active'], name='standalone__vpn_typ_08e367_idx'),
        ),
        migrations.AddIndex(
            model_name='standalonevpnconfiguration',
            index=models.Index(fields=['name'], name='standalone__name_f040aa_idx'),
        ),
        migrations.AddIndex(
            model_name='standaloneftpconfiguration',
            index=models.Index(fields=['host', 'port'], name='standalone__host_8571f6_idx'),
        ),
        migrations.AddIndex(
            model_name='standaloneftpconfiguration',
            index=models.Index(fields=['name'], name='standalone__name_98e0d1_idx'),
        ),
        migrations.AddIndex(
            model_name='standaloneftpconfiguration',
            index=models.Index(fields=['is_active'], name='standalone__is_acti_bcd70d_idx'),
        ),
        migrations.AddIndex(
            model_name='jingledetection',
            index=models.Index(fields=['channel', 'detected_at'], name='jingle_dete_channel_18fbef_idx'),
        ),
        migrations.AddIndex(
            model_name='jingledetection',
            index=models.Index(fields=['jingle', 'detected_at'], name='jingle_dete_jingle__5ec887_idx'),
        ),
        migrations.AddIndex(
            model_name='jingledetection',
            index=models.Index(fields=['start_timestamp', 'end_timestamp'], name='jingle_dete_start_t_8492c4_idx'),
        ),
        migrations.AddIndex(
            model_name='jingledetection',
            index=models.Index(fields=['status', 'detected_at'], name='jingle_dete_status_a1756a_idx'),
        ),
        migrations.AddIndex(
            model_name='jingledetection',
            index=models.Index(fields=['confidence_score'], name='jingle_dete_confide_879f92_idx'),
        ),
        migrations.AddIndex(
            model_name='jingle',
            index=models.Index(fields=['channel', 'is_active'], name='jingles_channel_d7c7d8_idx'),
        ),
        migrations.AddIndex(
            model_name='jingle',
            index=models.Index(fields=['placement_type', 'is_active'], name='jingles_placeme_150487_idx'),
        ),
        migrations.AddIndex(
            model_name='jingle',
            index=models.Index(fields=['priority', 'is_active', 'created_at'], name='jingles_priorit_b81a38_idx'),
        ),
        migrations.AddConstraint(
            model_name='jingle',
            constraint=models.CheckConstraint(check=models.Q(('duration__gte', 0)), name='positive_duration'),
        ),
        migrations.AddConstraint(
            model_name='jingle',
            constraint=models.CheckConstraint(check=models.Q(('file_size__gte', 0)), name='positive_file_size'),
        ),
        migrations.AddIndex(
            model_name='epgprogram',
            index=models.Index(fields=['channel', 'start_time'], name='epg_channel_start_idx'),
        ),
        migrations.AddIndex(
            model_name='epgprogram',
            index=models.Index(fields=['start_time', 'end_time'], name='epg_time_range_idx'),
        ),
        migrations.AddIndex(
            model_name='epgprogram',
            index=models.Index(fields=['program_type'], name='epg_type_idx'),
        ),
        migrations.AddConstraint(
            model_name='epgprogram',
            constraint=models.CheckConstraint(check=models.Q(('end_time__gt', models.F('start_time'))), name='epg_valid_time_range'),
        ),
        migrations.AddConstraint(
            model_name='epgprogram',
            constraint=models.CheckConstraint(check=models.Q(('duration__gt', 0)), name='epg_positive_duration'),
        ),
        migrations.AddIndex(
            model_name='channelzonerelation',
            index=models.Index(fields=['channel', 'zone'], name='channel_zon_channel_35e2ee_idx'),
        ),
        migrations.AddIndex(
            model_name='channelzonerelation',
            index=models.Index(fields=['zone', 'is_active'], name='channel_zon_zone_id_c83795_idx'),
        ),
        migrations.AddIndex(
            model_name='channelzonerelation',
            index=models.Index(fields=['channel', 'is_active', 'priority'], name='channel_zon_channel_01b275_idx'),
        ),
        migrations.AlterUniqueTogether(
            name='channelzonerelation',
            unique_together={('channel', 'zone')},
        ),
        migrations.AddIndex(
            model_name='channelschedule',
            index=models.Index(fields=['channel', 'start_time'], name='schedule_channel_start_idx'),
        ),
        migrations.AddIndex(
            model_name='channelschedule',
            index=models.Index(fields=['schedule_type'], name='schedule_type_idx'),
        ),
        migrations.AddIndex(
            model_name='channelschedule',
            index=models.Index(fields=['is_active', 'start_time'], name='schedule_active_start_idx'),
        ),
        migrations.AddConstraint(
            model_name='channelschedule',
            constraint=models.CheckConstraint(check=models.Q(('end_time__gt', models.F('start_time'))), name='schedule_valid_time_range'),
        ),
        migrations.AddConstraint(
            model_name='channelschedule',
            constraint=models.CheckConstraint(check=models.Q(('priority__gte', 1)), name='schedule_positive_priority'),
        ),
        migrations.AddIndex(
            model_name='channel',
            index=models.Index(fields=['status', 'is_online'], name='channels_status_9488f5_idx'),
        ),
        migrations.AddIndex(
            model_name='channel',
            index=models.Index(fields=['channel_type', 'category'], name='channels_channel_b7eea9_idx'),
        ),
        migrations.AddIndex(
            model_name='channel',
            index=models.Index(fields=['last_health_check'], name='channels_last_he_da88f4_idx'),
        ),
        migrations.AddIndex(
            model_name='adbreak',
            index=models.Index(fields=['start_at'], name='idx_start_at'),
        ),
        migrations.AddIndex(
            model_name='adbreak',
            index=models.Index(fields=['end_at'], name='idx_end_at'),
        ),
    ]
