from django.db import models


class RouterMonSettings(models.Model):
    """Singleton (pk=1) — router syslog receiver configuration."""

    enabled = models.BooleanField(default=False)
    syslog_port = models.IntegerField(
        default=5514,
        help_text=(
            'UDP port to listen on for syslog datagrams. Default: 5514 (non-privileged). '
            'If your router only supports port 514, add an iptables redirect on the k3s node: '
            'iptables -t nat -A PREROUTING -p udp --dport 514 -j REDIRECT --to-port 5514'
        ),
    )
    excluded_clients = models.TextField(
        blank=True,
        default='',
        help_text='One LAN IP per line. DNS queries from these clients will not be stored.',
    )
    retention_days = models.IntegerField(
        default=7,
        help_text='Delete DNS query records older than this many days.',
    )
    last_received_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        verbose_name = 'Router Monitor Settings'
        verbose_name_plural = 'Router Monitor Settings'

    def __str__(self):
        status = 'enabled' if self.enabled else 'disabled'
        return f'RouterMon Settings ({status}, port {self.syslog_port})'

    @classmethod
    def get(cls):
        obj, _ = cls.objects.get_or_create(pk=1)
        return obj


class DnsQuery(models.Model):
    """One DNS query event received from the router's dnsmasq syslog."""

    timestamp = models.DateTimeField(db_index=True)
    client_ip = models.GenericIPAddressField(db_index=True)
    client_name = models.CharField(max_length=200, blank=True, help_text='Hostname from DHCP lease at query time')
    domain = models.CharField(max_length=500, db_index=True)
    query_type = models.CharField(max_length=20, default='A')
    is_nxdomain = models.BooleanField(default=False, db_index=True)
    # Best-effort: first public A/AAAA record from the corresponding reply line.
    resolved_ip = models.GenericIPAddressField(null=True, blank=True)
    # Geo for resolved_ip (populated asynchronously)
    country = models.CharField(max_length=100, blank=True)
    country_code = models.CharField(max_length=10, blank=True)
    city = models.CharField(max_length=100, blank=True)

    class Meta:
        ordering = ['-timestamp']
        indexes = [
            models.Index(fields=['client_ip', 'timestamp']),
            models.Index(fields=['domain', 'timestamp']),
            models.Index(fields=['timestamp', 'is_nxdomain']),
        ]

    def __str__(self):
        flag = ' [NX]' if self.is_nxdomain else ''
        return f'{self.client_ip} → {self.domain} ({self.query_type}){flag} @ {self.timestamp:%Y-%m-%d %H:%M:%S}'

    @property
    def geo_display(self):
        parts = [p for p in [self.city, self.country] if p]
        return ', '.join(parts) if parts else '—'


class WanEvent(models.Model):
    """One incoming WAN connection attempt logged by iptables (WAN_IN: prefix)."""

    timestamp = models.DateTimeField(db_index=True)
    src_ip = models.GenericIPAddressField(db_index=True)
    dst_port = models.IntegerField(null=True, blank=True, db_index=True)
    protocol = models.CharField(max_length=10)   # TCP / UDP / ICMP
    src_port = models.IntegerField(null=True, blank=True)
    # Geo for src_ip (populated asynchronously)
    country = models.CharField(max_length=100, blank=True)
    country_code = models.CharField(max_length=10, blank=True)
    city = models.CharField(max_length=100, blank=True)
    isp = models.CharField(max_length=200, blank=True)

    class Meta:
        ordering = ['-timestamp']
        indexes = [
            models.Index(fields=['src_ip', 'timestamp']),
            models.Index(fields=['dst_port', 'timestamp']),
            models.Index(fields=['timestamp', 'protocol']),
        ]

    def __str__(self):
        port = f':{self.dst_port}' if self.dst_port else ''
        return f'{self.src_ip} → {self.protocol}{port} @ {self.timestamp:%Y-%m-%d %H:%M:%S}'

    @property
    def geo_display(self):
        parts = [p for p in [self.city, self.country] if p]
        return ', '.join(parts) if parts else '—'


class DhcpLease(models.Model):
    """Latest-known DHCP lease: maps LAN IP to MAC + hostname."""

    ip = models.GenericIPAddressField(unique=True, db_index=True)
    mac = models.CharField(max_length=17, blank=True)
    hostname = models.CharField(max_length=200, blank=True)
    last_seen = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['ip']

    def __str__(self):
        return f'{self.ip} ({self.hostname or self.mac or "unknown"})'
