"""
Domain handling utilities for the DecentraBrowser system.
"""
import os
import json
import re
from datetime import datetime
from .constants import DOMAIN_FORMAT

class Domain:
    """Class representing a domain in the DecentraBrowser system."""
    
    def __init__(self, prefix, main, suffix, ip=None, port=None):
        """Initialize a new domain."""
        self.prefix = prefix
        self.main = main
        self.suffix = suffix
        self.ip = ip
        self.port = port
        self.last_seen = datetime.utcnow().isoformat()
        self.favicon = None
        self.banner = None
        self.title = None
        self.file_count = 0
    
    @property
    def full_name(self):
        """Get the full domain name."""
        return DOMAIN_FORMAT.format(
            prefix=self.prefix,
            main=self.main,
            suffix=self.suffix
        )
    
    @property
    def address(self):
        """Get the full address (ip:port) for this domain."""
        if self.ip and self.port:
            return f"{self.ip}:{self.port}"
        return None
    
    @classmethod
    def from_full_name(cls, full_name, ip=None, port=None):
        """Create a Domain instance from a full domain name."""
        parts = full_name.split('.')
        if len(parts) != 4 or parts[3] != 'domain':
            raise ValueError(f"Invalid domain format: {full_name}")
        
        return cls(
            prefix=parts[0],
            main=parts[1],
            suffix=parts[2],
            ip=ip,
            port=port
        )
    
    def to_dict(self):
        """Convert the domain to a dictionary."""
        return {
            'prefix': self.prefix,
            'main': self.main,
            'suffix': self.suffix,
            'full_name': self.full_name,
            'ip': self.ip,
            'port': self.port,
            'address': self.address,
            'last_seen': self.last_seen,
            'favicon': self.favicon,
            'banner': self.banner,
            'title': self.title,
            'file_count': self.file_count
        }
    
    @classmethod
    def from_dict(cls, data):
        """Create a Domain instance from a dictionary."""
        domain = cls(
            prefix=data['prefix'],
            main=data['main'],
            suffix=data['suffix'],
            ip=data.get('ip'),
            port=data.get('port')
        )
        domain.last_seen = data.get('last_seen', datetime.utcnow().isoformat())
        domain.favicon = data.get('favicon')
        domain.banner = data.get('banner')
        domain.title = data.get('title')
        domain.file_count = data.get('file_count', 0)
        return domain
    
    def __str__(self):
        """String representation of the domain."""
        return f"{self.full_name} ({self.address})"


class DomainRegistry:
    """Class for managing domain registrations."""
    
    def __init__(self, registry_file):
        """Initialize the domain registry."""
        self.registry_file = registry_file
        self.domains = {}
        self.load()
    
    def load(self):
        """Load the domain registry from file."""
        try:
            with open(self.registry_file, 'r') as f:
                data = json.load(f)
                for domain_data in data.values():
                    domain = Domain.from_dict(domain_data)
                    self.domains[domain.full_name] = domain
        except (FileNotFoundError, json.JSONDecodeError):
            self.domains = {}
    
    def save(self):
        """Save the domain registry to file."""
        os.makedirs(os.path.dirname(self.registry_file), exist_ok=True)
        with open(self.registry_file, 'w') as f:
            json.dump({d.full_name: d.to_dict() for d in self.domains.values()}, f, indent=2)
    
    def register(self, domain):
        """Register a domain in the registry."""
        if not domain.ip or not domain.port:
            raise ValueError("Domain must have IP and port to register")
        
        domain.last_seen = datetime.utcnow().isoformat()
        self.domains[domain.full_name] = domain
        self.save()
        return True
    
    def unregister(self, domain_name):
        """Remove a domain from the registry."""
        if domain_name in self.domains:
            del self.domains[domain_name]
            self.save()
            return True
        return False
    
    def get_domain(self, domain_name):
        """Get a domain by name."""
        return self.domains.get(domain_name)
    
    def update_domain(self, domain_name, **kwargs):
        """Update domain properties."""
        if domain_name not in self.domains:
            return False
        
        domain = self.domains[domain_name]
        for key, value in kwargs.items():
            if hasattr(domain, key):
                setattr(domain, key, value)
        
        domain.last_seen = datetime.utcnow().isoformat()
        self.save()
        return True
    
    def list_domains(self):
        """List all registered domains."""
        return list(self.domains.values())
    
    def prune_inactive(self, max_age_hours=24):
        """Remove domains that haven't been seen recently."""
        now = datetime.utcnow()
        to_remove = []
        
        for name, domain in self.domains.items():
            last_seen = datetime.fromisoformat(domain.last_seen)
            age = (now - last_seen).total_seconds() / 3600  # hours
            
            if age > max_age_hours:
                to_remove.append(name)
        
        for name in to_remove:
            del self.domains[name]
        
        if to_remove:
            self.save()
        
        return len(to_remove)