"""
Integrations Celery tasks

This module contains tasks for:
1. Fetching surveys from HIS systems (every 25 minutes)
2. Testing HIS connection
"""

import logging
from datetime import datetime

from celery import shared_task
from django.utils import timezone

logger = logging.getLogger("apps.integrations")


# =============================================================================
# HIS Survey Fetching Tasks
# =============================================================================


def _parse_his_date(date_str):
    """Parse HIS date format 'DD-Mon-YYYY HH:MM:SS' to timezone-aware datetime."""
    if not date_str:
        return None
    for fmt in ("%d-%b-%Y %H:%M:%S", "%d-%b-%Y %H:%M"):
        try:
            naive = datetime.strptime(date_str, fmt)
            return timezone.make_aware(naive)
        except ValueError:
            continue
    return None


@shared_task
def fetch_his_surveys(from_date_str=None, to_date_str=None):
    """
    Periodic task to fetch patient data from HIS system every 5 minutes.

    This task:
    1. Connects to configured HIS API endpoints
    2. Fetches all patients from the last 5 minutes (or custom date range)
    3. Saves patient and visit data for every patient (all types)
    4. Creates surveys only for patients whose visit is complete:
       - ED/IP: DischargeDate present
       - OP: last visit event is older than configured delay hours

    Args:
        from_date_str: Optional override - fetch from this date (DD-Mon-YYYY HH:MM:SS)
        to_date_str: Optional override - fetch until this date (DD-Mon-YYYY HH:MM:SS)

    Scheduled to run every 5 minutes via Celery Beat.

    Returns:
        dict: Summary of fetched and processed data
    """
    from datetime import datetime, timedelta

    from apps.integrations.services.his_adapter import HISAdapter
    from apps.integrations.services.his_client import HISClient, HISClientFactory

    logger.info("Starting HIS patient data fetch task")

    result = {
        "success": False,
        "clients_processed": 0,
        "total_patients": 0,
        "visits_saved": 0,
        "surveys_created": 0,
        "errors": [],
        "details": [],
    }

    try:
        clients = HISClientFactory.get_all_active_clients()

        if not clients:
            msg = "No active HIS configurations found"
            logger.warning(msg)
            result["errors"].append(msg)
            return result

        if from_date_str and to_date_str:
            fetch_since = _parse_his_date(from_date_str)
            fetch_until = _parse_his_date(to_date_str)
            if not fetch_since or not fetch_until:
                msg = f"Invalid date format: from_date={from_date_str}, to_date={to_date_str}"
                result["errors"].append(msg)
                return result
            logger.info(f"Using custom date range: {fetch_since} to {fetch_until}")
        else:
            fetch_since = timezone.now() - timedelta(minutes=5)
            fetch_until = None

        logger.info(f"Fetching patient data since {fetch_since}")

        for client in clients:
            client_result = {
                "config": client.config.name if client.config else "Default",
                "total_patients": 0,
                "visits_saved": 0,
                "surveys_created": 0,
                "errors": [],
            }

            try:
                connection_test = client.test_connection()
                if not connection_test["success"]:
                    error_msg = f"HIS connection failed for {client_result['config']}: {connection_test['message']}"
                    logger.error(error_msg)
                    client_result["errors"].append(error_msg)
                    result["details"].append(client_result)
                    continue

                logger.info(f"Fetching patient data from {client_result['config']}")

                his_data = client.fetch_patient_data(since=fetch_since, until=fetch_until)

                if not his_data:
                    logger.info(f"No data returned from {client_result['config']}")
                    result["details"].append(client_result)
                    continue

                patient_list = his_data.get("FetchPatientDataTimeStampList", [])
                client_result["total_patients"] = len(patient_list)
                result["total_patients"] += len(patient_list)

                if not patient_list:
                    logger.info(f"No patients found in {client_result['config']}")
                    result["details"].append(client_result)
                    continue

                logger.info(f"Fetched {len(patient_list)} patients from {client_result['config']}")

                process_result = HISAdapter.process_his_response(his_data)

                client_result["visits_saved"] = process_result.get("visits_saved", 0)
                client_result["surveys_created"] = process_result.get("surveys_created", 0)
                client_result["errors"] = process_result.get("errors", [])

                result["visits_saved"] += client_result["visits_saved"]
                result["surveys_created"] += client_result["surveys_created"]
                result["errors"].extend(client_result["errors"])

                if client.config:
                    client.config.last_sync_at = timezone.now()
                    client.config.save(update_fields=["last_sync_at"])

                result["clients_processed"] += 1

            except Exception as e:
                error_msg = f"Error processing HIS client {client_result['config']}: {str(e)}"
                logger.error(error_msg, exc_info=True)
                client_result["errors"].append(error_msg)

            result["details"].append(client_result)

        result["success"] = True

        logger.info(
            f"HIS fetch completed: {result['clients_processed']} clients, "
            f"{result['total_patients']} patients, "
            f"{result['visits_saved']} visits saved, "
            f"{result['surveys_created']} surveys created"
        )

    except Exception as e:
        error_msg = f"Fatal error in fetch_his_surveys task: {str(e)}"
        logger.error(error_msg, exc_info=True)
        result["errors"].append(error_msg)

    return result


@shared_task
def test_his_connection(config_id=None):
    """
    Test connectivity to HIS system.

    Args:
        config_id: Optional IntegrationConfig ID. If not provided,
                  tests the default HIS configuration.

    Returns:
        dict: Connection test results
    """
    from apps.integrations.models import IntegrationConfig, SourceSystem
    from apps.integrations.services.his_client import HISClient

    logger.info(f"Testing HIS connection for config_id={config_id}")

    try:
        if config_id:
            config = IntegrationConfig.objects.filter(id=config_id, source_system=SourceSystem.HIS).first()
            if not config:
                return {"success": False, "message": f"HIS configuration with ID {config_id} not found"}
            client = HISClient(config)
        else:
            client = HISClient()

        result = client.test_connection()
        logger.info(f"HIS connection test result: {result}")
        return result

    except Exception as e:
        error_msg = f"Error testing HIS connection: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return {"success": False, "message": error_msg}


@shared_task
def sync_his_survey_mappings():
    """
    Sync survey template mappings from HIS system.

    This task can be scheduled periodically to sync any mapping
    configurations from the HIS system.

    Returns:
        dict: Sync results
    """
    from apps.integrations.models import SurveyTemplateMapping
    from apps.organizations.models import Hospital

    logger.info("Starting HIS survey mappings sync")

    result = {"success": True, "mappings_synced": 0, "errors": []}

    try:
        # Get all active mappings
        mappings = SurveyTemplateMapping.objects.filter(is_active=True)

        for mapping in mappings:
            try:
                # Validate mapping
                if not mapping.survey_template:
                    result["errors"].append(f"Mapping {mapping.id} has no survey template")
                    continue

                # Additional sync logic can be added here
                # e.g., fetching updated mapping rules from HIS

                result["mappings_synced"] += 1

            except Exception as e:
                result["errors"].append(f"Error syncing mapping {mapping.id}: {str(e)}")

        logger.info(f"HIS survey mappings sync completed: {result['mappings_synced']} mappings")

    except Exception as e:
        error_msg = f"Error syncing HIS mappings: {str(e)}"
        logger.error(error_msg, exc_info=True)
        result["success"] = False
        result["errors"].append(error_msg)

    return result
