"""
Enhanced API endpoints for logs with compression and file support
"""
from flask import Blueprint, request, jsonify
from werkzeug.utils import secure_filename
import os
import hashlib
from datetime import datetime
from app.services.log_service import LogCompressionService
from app.services.file_service import FileUploadService
from app.models import Device, LogEntry, FileUpload, WMTUpdateRequest
from config.database_config import get_db
import logging

logger = logging.getLogger(__name__)

# Create blueprint
logs_bp = Blueprint('logs', __name__, url_prefix='/api/logs')

# Initialize services
log_service = LogCompressionService()
file_service = FileUploadService()

@logs_bp.route('/', methods=['POST'])
@logs_bp.route('/submit', methods=['POST'])
def submit_log():
    """
    Enhanced log submission with compression support
    
    Expected JSON:
    {
        "hostname": "device-01",
        "device_ip": "192.168.1.100",
        "nume_masa": "Masa-01",
        "log_message": "Card detected: ABC123",
        "severity": "info",  # optional: debug, info, warning, error, critical
        "source_file": "/path/to/logfile.log",  # optional
        "metadata": {}  # optional additional metadata
    }
    """
    try:
        # Validate content type
        if not request.is_json:
            return jsonify({
                'error': 'Content-Type must be application/json',
                'success': False
            }), 400
        
        data = request.get_json()
        
        # Validate required fields
        required_fields = ['hostname', 'device_ip', 'nume_masa', 'log_message']
        missing_fields = [field for field in required_fields if not data.get(field)]
        
        if missing_fields:
            return jsonify({
                'error': f'Missing required fields: {", ".join(missing_fields)}',
                'success': False
            }), 400
        
        # Prepare device info
        device_info = {
            'hostname': data['hostname'],
            'device_ip': data['device_ip'],
            'nume_masa': data['nume_masa'],
            # Optional – clients can send these to keep device records up to date
            'device_type': data.get('device_type') or (data.get('metadata') or {}).get('device_type'),
            'os_version':  data.get('os_version')  or (data.get('metadata') or {}).get('os_version'),
            'location':    data.get('location')    or (data.get('metadata') or {}).get('location'),
            'mac_address': data.get('mac_address') or (data.get('metadata') or {}).get('mac_address'),
        }

        # ── Unconfigured device interception ──────────────────────────────────
        # A device with work_place=notconfig must NOT be added to the devices
        # table. Instead, create/refresh a "to_be_configured" update request so
        # it appears in the dedicated section on the Update Requests page.
        if data['nume_masa'].strip().lower() == 'notconfig':
            return _handle_notconfig_device(device_info, data.get('log_message', ''))
        # ─────────────────────────────────────────────────────────────────────

        # Process log with compression
        result = log_service.process_log_message(
            device_info=device_info,
            message=data['log_message'],
            severity=data.get('severity', 'info')
        )
        
        if result['success']:
            # Prepare response with compression info
            response_data = {
                'success': True,
                'message': 'Log processed successfully',
                'log_id': result['log_id'],
                'device_id': result['device_id'],
                'compression_info': result['compression']
            }
            
            # Add alias info if template was used
            if result['compression'].get('used_template'):
                response_data['template_alias'] = result['compression']['template_alias']
                
                # For clients: suggest using alias in future requests
                if result['compression'].get('new_template'):
                    response_data['suggestion'] = f"For similar messages, you can use template alias: {result['compression']['template_alias']}"
            
            return jsonify(response_data), 201
        else:
            return jsonify(result), 500
            
    except Exception as e:
        logging.error(f"Error in submit_log: {e}")
        return jsonify({
            'error': 'Internal server error',
            'success': False
        }), 500

@logs_bp.route('/template/<alias>', methods=['POST'])
def submit_templated_log():
    """
    Submit log using template alias (smaller payload)
    
    Expected JSON:
    {
        "alias": "CD001",
        "variables": {"card_id": "ABC123"},
        "device_info": {
            "hostname": "device-01",
            "device_ip": "192.168.1.100", 
            "nume_masa": "Masa-01"
        }
    }
    """
    try:
        data = request.get_json()
        alias = request.view_args['alias']
        
        # Validate required fields
        if not data.get('device_info'):
            return jsonify({
                'error': 'device_info is required',
                'success': False
            }), 400
        
        # Get template message
        variables = data.get('variables', {})
        full_message = log_service.get_message_by_alias(alias, variables)
        
        if not full_message:
            return jsonify({
                'error': f'Template alias {alias} not found',
                'success': False
            }), 404
        
        # Process as regular log
        result = log_service.process_log_message(
            device_info=data['device_info'],
            message=full_message,
            severity=data.get('severity', 'info')
        )
        
        return jsonify(result), 201 if result['success'] else 500
        
    except Exception as e:
        logging.error(f"Error in submit_templated_log: {e}")
        return jsonify({
            'error': 'Internal server error',
            'success': False
        }), 500

@logs_bp.route('/file', methods=['POST'])
def upload_log_file():
    """
    Upload log file for processing
    
    Expects multipart/form-data with:
    - file: log file
    - device_info: JSON string with device information
    """
    try:
        # Check if file was uploaded
        if 'file' not in request.files:
            return jsonify({
                'error': 'No file uploaded',
                'success': False
            }), 400
        
        file = request.files['file']
        if file.filename == '':
            return jsonify({
                'error': 'No file selected',
                'success': False
            }), 400
        
        # Get device info
        device_info_str = request.form.get('device_info')
        if not device_info_str:
            return jsonify({
                'error': 'device_info is required',
                'success': False
            }), 400
        
        import json
        device_info = json.loads(device_info_str)
        
        # Process file upload
        result = file_service.process_uploaded_file(file, device_info)
        
        return jsonify(result), 201 if result['success'] else 500
        
    except Exception as e:
        logging.error(f"Error in upload_log_file: {e}")
        return jsonify({
            'error': 'Internal server error',
            'success': False
        }), 500

def _handle_notconfig_device(device_info: dict, log_message: str):
    """
    A device reporting work_place='notconfig' is awaiting admin configuration.
    We must NOT create a Device record for it.  Instead we create / refresh a
    WMTUpdateRequest with status='to_be_configured' so it surfaces under the
    dedicated tab on the Update Requests page.
    """
    mac  = (device_info.get('mac_address') or '').strip().lower()
    hostname = device_info.get('hostname', '')
    ip       = device_info.get('device_ip', '')

    try:
        with get_db().get_session() as session:
            existing = (
                session.query(WMTUpdateRequest)
                .filter_by(mac_address=mac, status='to_be_configured')
                .order_by(WMTUpdateRequest.submitted_at.desc())
                .first()
            ) if mac else None

            if existing:
                # Refresh the timestamp and any identity fields that may have changed
                existing.submitted_at       = datetime.utcnow()
                existing.proposed_hostname  = hostname or existing.proposed_hostname
                existing.proposed_device_ip = ip       or existing.proposed_device_ip
                if log_message:
                    existing.admin_notes = f"Last log: {log_message[:200]}"
                logger.debug(f'notconfig heartbeat refreshed for {mac or hostname}')
            else:
                req = WMTUpdateRequest(
                    mac_address=mac or None,
                    device_id=None,
                    proposed_device_name=None,
                    proposed_hostname=hostname or None,
                    proposed_device_ip=ip or None,
                    client_config_mtime=datetime.utcnow().isoformat(),
                    submitted_at=datetime.utcnow(),
                    status='to_be_configured',
                    admin_notes=f"Last log: {log_message[:200]}" if log_message else None,
                )
                session.add(req)
                logger.info(f'New unconfigured device queued: {hostname} / {mac or "no-mac"}')

        return jsonify({
            'success': True,
            'status': 'to_be_configured',
            'message': 'Device is not configured. Awaiting admin assignment.',
        }), 202
    except Exception as e:
        logger.error(f'Error handling notconfig device: {e}')
        return jsonify({'success': False, 'error': str(e)}), 500


@logs_bp.route('/query', methods=['GET'])
def query_logs():
    """
    Query logs with filters and pagination

    Query parameters:
    - device_id: Filter by device ID
    - hostname: Filter by hostname
    - severity: Filter by severity level
    - start_time: Start time (ISO format)
    - end_time: End time (ISO format)
    - limit: Number of results (default 100)
    - offset: Offset for pagination (default 0)
    - include_template: Include resolved template messages (default true)
    """
    try:
        with get_db().get_session() as session:
            # Build query
            query = session.query(LogEntry).join(Device)
            
            # Apply filters
            if request.args.get('device_id'):
                query = query.filter(LogEntry.device_id == int(request.args.get('device_id')))
            
            if request.args.get('hostname'):
                query = query.filter(Device.hostname == request.args.get('hostname'))
            
            if request.args.get('severity'):
                query = query.filter(LogEntry.severity == request.args.get('severity'))
            
            if request.args.get('start_time'):
                start_time = datetime.fromisoformat(request.args.get('start_time'))
                query = query.filter(LogEntry.timestamp >= start_time)
            
            if request.args.get('end_time'):
                end_time = datetime.fromisoformat(request.args.get('end_time'))
                query = query.filter(LogEntry.timestamp <= end_time)
            
            # Pagination
            limit = min(int(request.args.get('limit', 100)), 1000)  # Max 1000
            offset = int(request.args.get('offset', 0))
            
            # Order by timestamp descending
            query = query.order_by(LogEntry.timestamp.desc())
            
            # Get total count
            total_count = query.count()
            
            # Apply pagination
            logs = query.limit(limit).offset(offset).all()
            
            # Format response
            include_template = request.args.get('include_template', 'true').lower() == 'true'
            log_data = []
            
            for log in logs:
                log_item = {
                    'id': log.id,
                    'device': {
                        'id': log.device.id,
                        'hostname': log.device.hostname,
                        'device_ip': log.device.device_ip,
                        'nume_masa': log.device.nume_masa
                    },
                    'timestamp': log.timestamp.isoformat(),
                    'severity': log.severity
                }
                
                if include_template and log.template:
                    log_item['message'] = log.resolved_message
                    log_item['template_alias'] = log.template.alias
                    log_item['template_category'] = log.template.category
                else:
                    log_item['message'] = log.full_message or log.resolved_message
                
                log_data.append(log_item)
            
            return jsonify({
                'success': True,
                'logs': log_data,
                'pagination': {
                    'total_count': total_count,
                    'limit': limit,
                    'offset': offset,
                    'has_more': offset + limit < total_count
                }
            })
            
    except Exception as e:
        logging.error(f"Error in query_logs: {e}")
        return jsonify({
            'error': 'Internal server error',
            'success': False
        }), 500

@logs_bp.route('/stats', methods=['GET'])
def get_log_stats():
    """Get logging and compression statistics"""
    try:
        # Get compression stats
        compression_stats = log_service.get_compression_stats()
        
        # Get additional stats
        with get_db().get_session() as session:
            # Device stats
            active_devices = session.query(Device).filter_by(status='active').count()
            total_devices = session.query(Device).count()
            
            # Recent activity
            from datetime import datetime, timedelta
            last_hour = datetime.utcnow() - timedelta(hours=1)
            recent_logs = session.query(LogEntry).filter(
                LogEntry.timestamp >= last_hour
            ).count()
            
            stats = {
                'success': True,
                'compression': compression_stats,
                'devices': {
                    'active': active_devices,
                    'total': total_devices
                },
                'activity': {
                    'logs_last_hour': recent_logs
                }
            }
            
            return jsonify(stats)
            
    except Exception as e:
        logging.error(f"Error in get_log_stats: {e}")
        return jsonify({
            'error': 'Internal server error',
            'success': False
        }), 500

@logs_bp.route('/templates', methods=['GET'])
def get_templates():
    """Get available message templates and aliases"""
    try:
        with get_db().get_session() as session:
            from app.models import MessageTemplate
            
            templates = session.query(MessageTemplate).order_by(
                MessageTemplate.usage_count.desc()
            ).all()
            
            template_data = [{
                'alias': template.alias,
                'category': template.category,
                'template_text': template.template_text,
                'usage_count': template.usage_count,
                'created_at': template.created_at.isoformat()
            } for template in templates]
            
            return jsonify({
                'success': True,
                'templates': template_data,
                'total_count': len(template_data)
            })
            
    except Exception as e:
        logging.error(f"Error in get_templates: {e}")
        return jsonify({
            'error': 'Internal server error',
            'success': False
        }), 500