# COPYRIGHT NOTICE
# This file is part of the "Universal Biomedical Skills" project.
# Copyright (c) 2026 MD BABU MIA, PhD <md.babu.mia@mssm.edu>
# All Rights Reserved.
#
# This code is proprietary and confidential.
# Unauthorized copying of this file, via any medium is strictly prohibited.
#
# Provenance: Authenticated by MD BABU MIA

"""Validation functions for OpenFDA API responses."""

import logging
from typing import Any

from .exceptions import OpenFDAValidationError

logger = logging.getLogger(__name__)


def validate_fda_response(
    response: dict[str, Any],
    required_fields: list[str] | None = None,
    response_type: str = "generic",
) -> bool:
    """
    Validate FDA API response structure.

    Args:
        response: The FDA API response dictionary
        required_fields: List of required top-level fields
        response_type: Type of response for specific validation

    Returns:
        True if valid

    Raises:
        OpenFDAValidationError: If validation fails
    """
    if not isinstance(response, dict):
        raise OpenFDAValidationError(
            f"Expected dict response, got {type(response).__name__}"
        )

    # Default required fields for most FDA responses
    if required_fields is None:
        required_fields = ["results"] if "results" in response else []

    # Check required fields
    missing_fields = [
        field for field in required_fields if field not in response
    ]
    if missing_fields:
        raise OpenFDAValidationError(
            f"Missing required fields in FDA response: {', '.join(missing_fields)}"
        )

    # Type-specific validation
    if response_type == "search":
        validate_search_response(response)
    elif response_type == "detail":
        validate_detail_response(response)

    return True


def validate_search_response(response: dict[str, Any]) -> bool:
    """
    Validate FDA search response structure.

    Args:
        response: FDA search response

    Returns:
        True if valid

    Raises:
        OpenFDAValidationError: If validation fails
    """
    # Search responses should have results array
    if "results" not in response:
        raise OpenFDAValidationError("Search response missing 'results' field")

    if not isinstance(response["results"], list):
        raise OpenFDAValidationError(
            f"Expected 'results' to be a list, got {type(response['results']).__name__}"
        )

    # If meta is present, validate it
    if "meta" in response:
        validate_meta_field(response["meta"])

    return True


def validate_detail_response(response: dict[str, Any]) -> bool:
    """
    Validate FDA detail response structure.

    Args:
        response: FDA detail response

    Returns:
        True if valid

    Raises:
        OpenFDAValidationError: If validation fails
    """
    # Detail responses usually have a single result
    if "results" in response:
        if not isinstance(response["results"], list):
            raise OpenFDAValidationError(
                f"Expected 'results' to be a list, got {type(response['results']).__name__}"
            )

        if len(response["results"]) == 0:
            # Empty results is valid (not found)
            return True

        if len(response["results"]) > 1:
            logger.warning(
                f"Detail response contains {len(response['results'])} results, expected 1"
            )

    return True


def validate_meta_field(meta: dict[str, Any]) -> bool:
    """
    Validate FDA response meta field.

    Args:
        meta: Meta field from FDA response

    Returns:
        True if valid

    Raises:
        OpenFDAValidationError: If validation fails
    """
    if not isinstance(meta, dict):
        raise OpenFDAValidationError(
            f"Expected 'meta' to be a dict, got {type(meta).__name__}"
        )

    # Check for results metadata
    if "results" in meta:
        results_meta = meta["results"]
        if not isinstance(results_meta, dict):
            raise OpenFDAValidationError(
                f"Expected 'meta.results' to be a dict, got {type(results_meta).__name__}"
            )

        # Validate pagination fields if present
        for field in ["skip", "limit", "total"]:
            if field in results_meta and not isinstance(
                results_meta[field], int | float
            ):
                raise OpenFDAValidationError(
                    f"Expected 'meta.results.{field}' to be numeric, "
                    f"got {type(results_meta[field]).__name__}"
                )

    return True


def validate_adverse_event(event: dict[str, Any]) -> bool:
    """
    Validate an adverse event record.

    Args:
        event: Adverse event record

    Returns:
        True if valid

    Raises:
        OpenFDAValidationError: If validation fails
    """
    if not isinstance(event, dict):
        raise OpenFDAValidationError(
            f"Expected adverse event to be a dict, got {type(event).__name__}"
        )

    # Key fields that should be present (but may be null)
    important_fields = ["patient", "safetyreportid"]

    for field in important_fields:
        if field not in event:
            logger.warning(f"Adverse event missing expected field: {field}")

    return True


def validate_drug_label(label: dict[str, Any]) -> bool:
    """
    Validate a drug label record.

    Args:
        label: Drug label record

    Returns:
        True if valid

    Raises:
        OpenFDAValidationError: If validation fails
    """
    if not isinstance(label, dict):
        raise OpenFDAValidationError(
            f"Expected drug label to be a dict, got {type(label).__name__}"
        )

    # Labels should have OpenFDA section
    if "openfda" not in label:
        logger.warning("Drug label missing 'openfda' section")

    # Should have at least one section
    label_sections = [
        "indications_and_usage",
        "contraindications",
        "warnings_and_precautions",
        "adverse_reactions",
        "dosage_and_administration",
    ]

    has_section = any(section in label for section in label_sections)
    if not has_section:
        logger.warning("Drug label has no standard sections")

    return True


def validate_device_event(event: dict[str, Any]) -> bool:
    """
    Validate a device event record.

    Args:
        event: Device event record

    Returns:
        True if valid

    Raises:
        OpenFDAValidationError: If validation fails
    """
    if not isinstance(event, dict):
        raise OpenFDAValidationError(
            f"Expected device event to be a dict, got {type(event).__name__}"
        )

    # Device events should have MDR report key
    if "mdr_report_key" not in event:
        logger.warning("Device event missing 'mdr_report_key'")

    # Should have device information
    if "device" not in event and "devices" not in event:
        logger.warning("Device event missing device information")

    return True


def validate_recall(recall: dict[str, Any]) -> bool:
    """
    Validate a recall record.

    Args:
        recall: Recall record

    Returns:
        True if valid

    Raises:
        OpenFDAValidationError: If validation fails
    """
    if not isinstance(recall, dict):
        raise OpenFDAValidationError(
            f"Expected recall to be a dict, got {type(recall).__name__}"
        )

    # Required fields for recalls
    required = ["recall_number", "classification", "product_description"]

    for field in required:
        if field not in recall:
            logger.warning(f"Recall missing required field: {field}")

    # Validate classification if present
    if "classification" in recall:
        valid_classes = ["Class I", "Class II", "Class III", "1", "2", "3"]
        if recall["classification"] not in valid_classes:
            logger.warning(
                f"Invalid recall classification: {recall['classification']}"
            )

    return True


def sanitize_response(response: dict[str, Any]) -> dict[str, Any]:
    """
    Sanitize FDA response to handle common issues.

    Args:
        response: Raw FDA response

    Returns:
        Sanitized response
    """
    if not response:
        return {}

    # Handle fields that can be string or list
    if "results" in response and isinstance(response["results"], list):
        for result in response["results"]:
            if isinstance(result, dict):
                # Fields that can be string or list
                polymorphic_fields = [
                    "source_type",
                    "remedial_action",
                    "medical_specialty_description",
                    "manufacturer_name",
                    "brand_name",
                    "generic_name",
                ]

                for field in polymorphic_fields:
                    if field in result:
                        value = result[field]
                        # Ensure consistent list format
                        if not isinstance(value, list):
                            result[field] = [value] if value else []

    return response

__AUTHOR_SIGNATURE__ = "9a7f3c2e-MD-BABU-MIA-2026-MSSM-SECURE"
