"""
HTTP endpoint for Firebase MCP server.
"""
from .tools import auth, firestore, storage
import json
import asyncio
from datetime import datetime
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from asgiref.sync import async_to_sync

# Custom JSON encoder for Firebase objects


class FirebaseJSONEncoder(json.JSONEncoder):
    """Custom JSON encoder that handles Firebase-specific objects."""

    def default(self, obj):
        # Handle Firebase DatetimeWithNanoseconds
        if hasattr(obj, 'timestamp'):
            # Convert to ISO format string
            return obj.isoformat() if hasattr(obj, 'isoformat') else str(obj)
        # Handle standard datetime objects
        elif isinstance(obj, datetime):
            return obj.isoformat()
        # Handle other non-serializable objects
        elif hasattr(obj, '__dict__'):
            return str(obj)
        return super().default(obj)


def safe_json_dumps(obj, **kwargs):
    """Safely serialize objects to JSON, handling Firebase objects."""
    return json.dumps(obj, cls=FirebaseJSONEncoder, **kwargs)


# Import all tool modules to register the tools

# Store all available tools
TOOLS = {
    'verify_id_token': auth.verify_id_token,
    'create_custom_token': auth.create_custom_token,
    'get_user': auth.get_user,
    'delete_user': auth.delete_user,
    'get_document': firestore.get_document,
    'create_document': firestore.create_document,
    'update_document': firestore.update_document,
    'delete_document': firestore.delete_document,
    'list_collections': firestore.list_collections,
    'query_collection': firestore.query_collection,
    'upload_file': storage.upload_file,
    'download_file': storage.download_file,
    'delete_file': storage.delete_file,
    'list_files': storage.list_files,
}

# Tool descriptions for MCP protocol
TOOL_DESCRIPTIONS = {
    'verify_id_token': {
        'name': 'verify_id_token',
        'description': 'Verify Firebase ID token',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'id_token': {'type': 'string', 'description': 'Firebase ID token to verify'}
            },
            'required': ['id_token']
        }
    },
    'create_custom_token': {
        'name': 'create_custom_token',
        'description': 'Create Firebase custom token',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'uid': {'type': 'string', 'description': 'User ID'},
                'additional_claims': {'type': 'object', 'description': 'Additional claims (optional)'}
            },
            'required': ['uid']
        }
    },
    'get_user': {
        'name': 'get_user',
        'description': 'Get Firebase user information',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'uid': {'type': 'string', 'description': 'User ID'}
            },
            'required': ['uid']
        }
    },
    'delete_user': {
        'name': 'delete_user',
        'description': 'Delete Firebase user',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'uid': {'type': 'string', 'description': 'User ID to delete'}
            },
            'required': ['uid']
        }
    },
    'get_document': {
        'name': 'get_document',
        'description': 'Get Firestore document',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'collection': {'type': 'string', 'description': 'Collection name'},
                'document_id': {'type': 'string', 'description': 'Document ID'}
            },
            'required': ['collection', 'document_id']
        }
    },
    'create_document': {
        'name': 'create_document',
        'description': 'Create Firestore document',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'collection': {'type': 'string', 'description': 'Collection name'},
                'document_id': {'type': 'string', 'description': 'Document ID (optional)'},
                'data': {'type': 'object', 'description': 'Document data'}
            },
            'required': ['collection', 'data']
        }
    },
    'update_document': {
        'name': 'update_document',
        'description': 'Update Firestore document',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'collection': {'type': 'string', 'description': 'Collection name'},
                'document_id': {'type': 'string', 'description': 'Document ID'},
                'data': {'type': 'object', 'description': 'Document data to update'}
            },
            'required': ['collection', 'document_id', 'data']
        }
    },
    'delete_document': {
        'name': 'delete_document',
        'description': 'Delete Firestore document',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'collection': {'type': 'string', 'description': 'Collection name'},
                'document_id': {'type': 'string', 'description': 'Document ID'}
            },
            'required': ['collection', 'document_id']
        }
    },
    'list_collections': {
        'name': 'list_collections',
        'description': 'List Firestore collections',
        'inputSchema': {
            'type': 'object',
            'properties': {},
            'required': []
        }
    },
    'query_collection': {
        'name': 'query_collection',
        'description': 'Query Firestore collection',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'collection': {'type': 'string', 'description': 'Collection name'},
                'limit': {'type': 'integer', 'description': 'Limit results (optional)'}
            },
            'required': ['collection']
        }
    },
    'upload_file': {
        'name': 'upload_file',
        'description': 'Upload file to Firebase Storage',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'file_path': {'type': 'string', 'description': 'Remote file path in storage'},
                'local_path': {'type': 'string', 'description': 'Local file path to upload'},
                'content_type': {'type': 'string', 'description': 'Content type (optional)'}
            },
            'required': ['file_path', 'local_path']
        }
    },
    'download_file': {
        'name': 'download_file',
        'description': 'Download file from Firebase Storage',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'file_path': {'type': 'string', 'description': 'Remote file path in storage'},
                'local_path': {'type': 'string', 'description': 'Local path to save file'}
            },
            'required': ['file_path', 'local_path']
        }
    },
    'delete_file': {
        'name': 'delete_file',
        'description': 'Delete file from Firebase Storage',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'file_path': {'type': 'string', 'description': 'Remote file path in storage'}
            },
            'required': ['file_path']
        }
    },
    'list_files': {
        'name': 'list_files',
        'description': 'List files in Firebase Storage',
        'inputSchema': {
            'type': 'object',
            'properties': {
                'prefix': {'type': 'string', 'description': 'Path prefix (optional)'},
                'max_results': {'type': 'integer', 'description': 'Maximum results (optional)'}
            },
            'required': []
        }
    }
}


@api_view(['POST', 'GET', 'OPTIONS'])
@csrf_exempt
def mcp_handler(request):
    """
    Handle MCP HTTP requests directly without using FastMCP's Starlette app.

    This implements the basic MCP HTTP protocol:
    - GET requests return server info and available tools
    - POST requests handle JSON-RPC 2.0 method calls
    """
    try:        # Handle CORS preflight
        if request.method == 'OPTIONS':
            response = HttpResponse('')
            response['Access-Control-Allow-Origin'] = '*'
            response['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
            response['Access-Control-Allow-Headers'] = 'Content-Type, Accept, Authorization'
            response['Access-Control-Max-Age'] = '86400'
            return response        # Handle GET requests - check if it's an SSE request
        if request.method == 'GET':
            accept_header = request.headers.get('Accept', '')

            # If client expects SSE, return 406 Not Acceptable since we don't support SSE
            if 'text/event-stream' in accept_header:
                response_data = {
                    'error': 'SSE not supported',
                    'message': 'This server only supports JSON-RPC 2.0 over HTTP POST',
                    'supported_methods': ['POST with JSON-RPC 2.0']
                }
                response = HttpResponse(
                    json.dumps(response_data),
                    content_type='application/json',
                    status=406  # Not Acceptable
                )
                response['Access-Control-Allow-Origin'] = '*'
                return response

            # Return server info for regular GET requests
            server_info = {
                'name': 'Firebase MCP Server',
                'version': '1.0.0',
                'description': 'Firebase Admin SDK MCP Server for Django',
                'protocol': 'JSON-RPC 2.0',
                'transport': 'HTTP',
                'capabilities': {
                    'tools': True,
                    'initialize': True
                },
                'tools': list(TOOL_DESCRIPTIONS.values())
            }
            response = HttpResponse(
                json.dumps(server_info, indent=2),
                content_type='application/json'
            )
            response['Access-Control-Allow-Origin'] = '*'
            return response

        # Handle POST requests - JSON-RPC 2.0 calls
        if request.method == 'POST':
            try:
                data = json.loads(request.body)
            except json.JSONDecodeError:
                return HttpResponse(
                    json.dumps({
                        'jsonrpc': '2.0',
                        'error': {
                            'code': -32700,
                            'message': 'Parse error'
                        },
                        'id': None
                    }),
                    content_type='application/json',
                    status=400
                )

            # Validate JSON-RPC 2.0 format
            if not isinstance(data, dict) or data.get('jsonrpc') != '2.0':
                return HttpResponse(
                    json.dumps({
                        'jsonrpc': '2.0',
                        'error': {
                            'code': -32600,
                            'message': 'Invalid Request'
                        },
                        'id': data.get('id')
                    }),
                    content_type='application/json',
                    status=400
                )

            method = data.get('method')
            params = data.get('params', {})
            # Handle initialize method - required for MCP protocol
            request_id = data.get('id')
            if method == 'initialize':
                # Return server capabilities and info
                response_data = {
                    'jsonrpc': '2.0',
                    'result': {
                        'protocolVersion': '2024-11-05',
                        'capabilities': {
                            'tools': {
                                'listChanged': False
                            }
                        },
                        'serverInfo': {
                            'name': 'Firebase MCP Server',
                            'version': '1.0.0'
                        }
                    },
                    'id': request_id
                }
                response = HttpResponse(
                    json.dumps(response_data),
                    content_type='application/json'
                )
                response['Access-Control-Allow-Origin'] = '*'
                return response

            # Handle tools/list method
            elif method == 'tools/list':
                response_data = {
                    'jsonrpc': '2.0',
                    'result': {
                        'tools': list(TOOL_DESCRIPTIONS.values())
                    },
                    'id': request_id
                }
                response = HttpResponse(
                    json.dumps(response_data),
                    content_type='application/json'
                )
                response['Access-Control-Allow-Origin'] = '*'
                return response

            # Handle notifications/initialized method
            elif method == 'notifications/initialized':
                # This is a notification (no response needed)
                response = HttpResponse(
                    '',
                    content_type='application/json',
                    status=204  # No Content
                )
                response['Access-Control-Allow-Origin'] = '*'
                return response

            # Handle tools/call method
            elif method == 'tools/call':
                tool_name = params.get('name')
                tool_arguments = params.get('arguments', {})

                if tool_name not in TOOLS:
                    response_data = {
                        'jsonrpc': '2.0',
                        'error': {
                            'code': -32601,
                            'message': f'Tool not found: {tool_name}'
                        },
                        'id': request_id
                    }
                    response = HttpResponse(
                        json.dumps(response_data),
                        content_type='application/json',
                        status=404
                    )
                    response['Access-Control-Allow-Origin'] = '*'
                    return response

                try:                    # Call the tool function
                    tool_func = TOOLS[tool_name]
                    result = async_to_sync(tool_func)(**tool_arguments)

                    response_data = {
                        'jsonrpc': '2.0',
                        'result': {
                            'content': [
                                {
                                    'type': 'text',
                                    'text': safe_json_dumps(result, indent=2)
                                }
                            ]
                        },
                        'id': request_id
                    }
                    response = HttpResponse(
                        json.dumps(response_data),
                        content_type='application/json'
                    )
                    response['Access-Control-Allow-Origin'] = '*'
                    return response

                except Exception as e:
                    response_data = {
                        'jsonrpc': '2.0',
                        'error': {
                            'code': -32000,
                            'message': f'Tool execution error: {str(e)}'
                        },
                        'id': request_id
                    }
                    response = HttpResponse(
                        safe_json_dumps(response_data),
                        content_type='application/json',
                        status=500
                    )
                    response['Access-Control-Allow-Origin'] = '*'
                    return response

            # Unknown method
            else:
                response_data = {
                    'jsonrpc': '2.0',
                    'error': {
                        'code': -32601,
                        'message': f'Method not found: {method}'
                    },
                    'id': request_id
                }
                response = HttpResponse(
                    json.dumps(response_data),
                    content_type='application/json',
                    status=404
                )
                response['Access-Control-Allow-Origin'] = '*'
                return response

    except Exception as e:
        import traceback
        traceback.print_exc()
        response_data = {
            'jsonrpc': '2.0',
            'error': {
                'code': -32000,
                'message': f'Internal server error: {str(e)}'
            },
            'id': None
        }
        response = HttpResponse(
            json.dumps(response_data),
            content_type='application/json',
            status=500
        )
        response['Access-Control-Allow-Origin'] = '*'
        return response
