"""
Central registration server for the DecentraBrowser system.
"""
import os
import json
import time
from flask import Flask, request, jsonify
import threading
from ..shared.constants import DEFAULT_CENTRAL_SERVER_PORT
from ..shared.domain import Domain, DomainRegistry
from ..shared.utils import setup_logging, ensure_directory_exists, get_data_dir

# Setup logger
logger = setup_logging('central_server')

class CentralServer:
    """Central registration server for the DecentraBrowser system."""
    
    def __init__(self, data_dir=None, port=DEFAULT_CENTRAL_SERVER_PORT):
        """Initialize the central server."""
        if data_dir is None:
            data_dir = get_data_dir() / 'central_server'
        
        self.data_dir = ensure_directory_exists(data_dir)
        self.registry_file = os.path.join(self.data_dir, 'registry.json')
        self.port = port
        
        # Initialize domain registry
        self.registry = DomainRegistry(self.registry_file)
        
        # Initialize Flask app
        self.app = Flask(__name__)
        self.setup_routes()
        
        # Background maintenance thread
        self.maintenance_thread = None
        self.running = False
    
    def setup_routes(self):
        """Setup the Flask routes."""
        
        @self.app.route('/api/register', methods=['POST'])
        def register_domain():
            """Register a new domain."""
            data = request.json
            
            if not data or not isinstance(data, dict):
                return jsonify({'success': False, 'error': 'Invalid data format'}), 400
            
            required_fields = ['prefix', 'main', 'suffix', 'ip', 'port']
            if not all(field in data for field in required_fields):
                return jsonify({'success': False, 'error': 'Missing required fields'}), 400
            
            try:
                domain = Domain(
                    prefix=data['prefix'],
                    main=data['main'],
                    suffix=data['suffix'],
                    ip=data['ip'],
                    port=data['port']
                )
                
                # Add optional metadata if provided
                if 'favicon' in data:
                    domain.favicon = data['favicon']
                if 'banner' in data:
                    domain.banner = data['banner']
                if 'title' in data:
                    domain.title = data['title']
                if 'file_count' in data:
                    domain.file_count = data['file_count']
                
                self.registry.register(domain)
                
                return jsonify({
                    'success': True,
                    'domain': domain.full_name,
                    'message': 'Domain registered successfully'
                })
                
            except Exception as e:
                logger.error(f"Error registering domain: {str(e)}")
                return jsonify({'success': False, 'error': str(e)}), 500
        
        @self.app.route('/api/unregister', methods=['POST'])
        def unregister_domain():
            """Unregister a domain."""
            data = request.json
            
            if not data or not isinstance(data, dict) or 'domain' not in data:
                return jsonify({'success': False, 'error': 'Invalid data format'}), 400
            
            domain_name = data['domain']
            result = self.registry.unregister(domain_name)
            
            if result:
                return jsonify({
                    'success': True,
                    'message': f'Domain {domain_name} unregistered successfully'
                })
            else:
                return jsonify({
                    'success': False,
                    'error': f'Domain {domain_name} not found'
                }), 404
        
        @self.app.route('/api/update', methods=['POST'])
        def update_domain():
            """Update domain information."""
            data = request.json
            
            if not data or not isinstance(data, dict) or 'domain' not in data:
                return jsonify({'success': False, 'error': 'Invalid data format'}), 400
            
            domain_name = data['domain']
            update_data = {k: v for k, v in data.items() if k != 'domain'}
            
            result = self.registry.update_domain(domain_name, **update_data)
            
            if result:
                return jsonify({
                    'success': True,
                    'message': f'Domain {domain_name} updated successfully'
                })
            else:
                return jsonify({
                    'success': False,
                    'error': f'Domain {domain_name} not found'
                }), 404
        
        @self.app.route('/api/sources', methods=['GET'])
        def list_domains():
            """List all active domains."""
            domains = self.registry.list_domains()
            return jsonify({
                'success': True,
                'count': len(domains),
                'domains': [d.to_dict() for d in domains]
            })
        
        @self.app.route('/api/resolve/<domain>', methods=['GET'])
        def resolve_domain(domain):
            """Resolve a domain name to its IP and port."""
            domain_obj = self.registry.get_domain(domain)
            
            if domain_obj:
                return jsonify({
                    'success': True,
                    'domain': domain,
                    'ip': domain_obj.ip,
                    'port': domain_obj.port
                })
            else:
                return jsonify({
                    'success': False,
                    'error': f'Domain {domain} not found'
                }), 404
        
        @self.app.route('/health', methods=['GET'])
        def health_check():
            """Health check endpoint."""
            return jsonify({
                'status': 'ok',
                'timestamp': time.time(),
                'domains': len(self.registry.list_domains())
            })
    
    def maintenance_task(self):
        """Background task to prune inactive domains."""
        while self.running:
            try:
                pruned = self.registry.prune_inactive()
                if pruned:
                    logger.info(f"Pruned {pruned} inactive domains")
            except Exception as e:
                logger.error(f"Error in maintenance task: {str(e)}")
            
            # Sleep for 1 hour
            for _ in range(60):  # Check every minute if we should stop
                if not self.running:
                    break
                time.sleep(60)
    
    def start(self):
        """Start the central server."""
        self.running = True
        
        # Start maintenance thread
        self.maintenance_thread = threading.Thread(target=self.maintenance_task)
        self.maintenance_thread.daemon = True
        self.maintenance_thread.start()
        
        # Start Flask app
        self.app.run(host='0.0.0.0', port=self.port)
    
    def stop(self):
        """Stop the central server."""
        self.running = False
        # Flask will be stopped by the caller


def main():
    """Entry point for the central server."""
    import argparse
    
    parser = argparse.ArgumentParser(description='DecentraBrowser Central Server')
    parser.add_argument('--port', type=int, default=DEFAULT_CENTRAL_SERVER_PORT,
                        help=f'Port to listen on (default: {DEFAULT_CENTRAL_SERVER_PORT})')
    parser.add_argument('--data-dir', type=str, default=None,
                        help='Data directory (default: platform-specific user data dir)')
    
    args = parser.parse_args()
    
    # Start the server
    server = CentralServer(data_dir=args.data_dir, port=args.port)
    try:
        logger.info(f"Starting central server on port {args.port}")
        server.start()
    except KeyboardInterrupt:
        logger.info("Shutting down central server")
        server.stop()


if __name__ == '__main__':
    main()