import json
from datetime import datetime
import logging
from typing import Dict, Any
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.utils.decorators import method_decorator
from django.views import View
from django.core.exceptions import ValidationError
from django.db import transaction
from .models import Source, JobPosting, IntegrationLog
from .erp_integration_service import ERPIntegrationService


class ERPIntegrationView(View):
    """
    API endpoint for receiving job requests from ERP system
    """

    def get(self, request):
        """Health check endpoint"""
        return JsonResponse({
            'status': 'success',
            'message': 'ERP Integration API is available',
            'version': '1.0.0',
            'supported_actions': ['create_job', 'update_job']
        })

    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)

    def post(self, request):
        """Handle POST requests from ERP system"""
        try:
            # Start timing for processing
            start_time = datetime.now()

            # Get request data
            if request.content_type == 'application/json':
                try:
                    data = json.loads(request.body.decode('utf-8'))
                except json.JSONDecodeError:
                    return JsonResponse({
                        'status': 'error',
                        'message': 'Invalid JSON data'
                    }, status=400)
            else:
                data = request.POST.dict()
            # Get action from request
            action = data.get('action', '').lower()
            if not action:
                return JsonResponse({
                    'status': 'error',
                    'message': 'Action is required'
                }, status=400)

            # Validate action
            valid_actions = ['create_job', 'update_job']
            if action not in valid_actions:
                return JsonResponse({
                    'status': 'error',
                    'message': f'Invalid action. Must be one of: {", ".join(valid_actions)}'
                }, status=400)

            # Get source identifier
            source_name = data.get('source_name')
            source_id = data.get('source_id')

            # Find the source
            source = None
            if source_id:
                source = Source.objects.filter(id=source_id).first()
            elif source_name:
                source = Source.objects.filter(name=source_name).first()

            if not source:
                return JsonResponse({
                    'status': 'error',
                    'message': 'Source not found'
                }, status=404)

            # Create integration service
            service = ERPIntegrationService(source)

            # Validate request
            is_valid, error_msg = service.validate_request(request)
            if not is_valid:
                service.log_integration_request(request, 'ERROR', error_message=error_msg, status_code='403')
                return JsonResponse({
                    'status': 'error',
                    'message': error_msg
                }, status=403)

            # Log the request
            service.log_integration_request(request, 'REQUEST')

            # Process based on action
            if action == 'create_job':
                result, error_msg = self._create_job(service, data)
            elif action == 'update_job':
                result, error_msg = self._update_job(service, data)

            # Calculate processing time
            processing_time = (datetime.now() - start_time).total_seconds()

            # Log the result
            status_code = '200' if not error_msg else '400'
            service.log_integration_request(
                request,
                'RESPONSE' if not error_msg else 'ERROR',
                response_data={'result': result} if result else {},
                status_code=status_code,
                processing_time=processing_time,
                error_message=error_msg
            )

            # Return response
            if error_msg:
                return JsonResponse({
                    'status': 'error',
                    'message': error_msg,
                    'processing_time': processing_time
                }, status=400)

            return JsonResponse({
                'status': 'success',
                'message': f'Job {action.replace("_", " ")} successfully',
                'data': result,
                'processing_time': processing_time
            })

        except Exception as e:
            logger = logging.getLogger(__name__)
            logger.error(f"Error in ERP integration: {str(e)}", exc_info=True)

            return JsonResponse({
                'status': 'error',
                'message': 'Internal server error'
            }, status=500)

    @transaction.atomic
    def _create_job(self, service: ERPIntegrationService, data: Dict[str, Any]) -> tuple[Dict[str, Any], str]:
        """Create a new job from ERP data"""
        # Validate ERP data
        is_valid, error_msg = service.validate_erp_data(data)
        if not is_valid:
            return None, error_msg

        # Create job from ERP data
        job, error_msg = service.create_job_from_erp(data)
        if error_msg:
            return None, error_msg

        # Prepare response data
        response_data = {
            'job_id': job.internal_job_id,
            'title': job.title,
            'status': job.status,
            'created_at': job.created_at.isoformat(),
            'message': 'Job created successfully'
        }

        return response_data, ""

    @transaction.atomic
    def _update_job(self, service: ERPIntegrationService, data: Dict[str, Any]) -> tuple[Dict[str, Any], str]:
        """Update an existing job from ERP data"""
        # Get job ID from request
        job_id = data.get('job_id')
        if not job_id:
            return None, "Job ID is required for update"

        # Validate ERP data
        is_valid, error_msg = service.validate_erp_data(data)
        if not is_valid:
            return None, error_msg

        # Update job from ERP data
        job, error_msg = service.update_job_from_erp(job_id, data)
        if error_msg:
            return None, error_msg

        # Prepare response data
        response_data = {
            'job_id': job.internal_job_id,
            'title': job.title,
            'status': job.status,
            'updated_at': job.updated_at.isoformat(),
            'message': 'Job updated successfully'
        }

        return response_data, ""


# Specific endpoint for creating jobs (POST only)
@require_http_methods(["POST"])
@csrf_exempt
def erp_create_job_view(request):
    """View for creating jobs from ERP (simpler endpoint)"""
    view = ERPIntegrationView()
    return view.post(request)


# Specific endpoint for updating jobs (POST only)
@require_http_methods(["POST"])
@csrf_exempt
def erp_update_job_view(request):
    """View for updating jobs from ERP (simpler endpoint)"""
    view = ERPIntegrationView()
    return view.post(request)


# Health check endpoint
@require_http_methods(["GET"])
def erp_integration_health(request):
    """Health check endpoint for ERP integration"""
    return JsonResponse({
        'status': 'healthy',
        'timestamp': datetime.now().isoformat(),
        'services': {
            'erp_integration': 'available',
            'database': 'connected'
        }
    })
