"""
Utilities for field value extraction and normalization.

Single source of truth for converting model instance field values
to their database representation. This eliminates duplicate FK handling
logic scattered across multiple components.
"""

import logging

from django.db.models import ForeignKey

logger = logging.getLogger(__name__)


def get_field_value_for_db(obj, field_name, model_cls=None):
    """
    Get a field value from an object in its database-ready form.

    For regular fields: returns the field value as-is
    For FK fields: returns the PK (integer) instead of the related object

    This ensures consistent handling across all operations (upsert classification,
    bulk create, bulk update, etc.)

    Args:
        obj: Model instance
        field_name: Name of the field to extract
        model_cls: Model class (optional, will infer from obj if not provided)

    Returns:
        Database-ready value (FK as integer, regular fields as-is)
    """
    if model_cls is None:
        model_cls = obj.__class__

    try:
        field = model_cls._meta.get_field(field_name)
    except Exception:  # noqa: BLE001
        # Field doesn't exist - just get attribute
        return getattr(obj, field_name, None)

    # Check if it's a ForeignKey
    if isinstance(field, ForeignKey):
        # For FK fields, always use attname (e.g., 'business_id' not 'business')
        # This gets the raw FK ID value from the database field
        return getattr(obj, field.attname, None)

    # Regular field - get normally
    return getattr(obj, field_name, None)


def get_field_values_for_db(obj, field_names, model_cls=None):
    """
    Get multiple field values from an object in database-ready form.

    Args:
        obj: Model instance
        field_names: List of field names
        model_cls: Model class (optional)

    Returns:
        Dict of {field_name: db_value}
    """
    if model_cls is None:
        model_cls = obj.__class__

    return {
        field_name: get_field_value_for_db(obj, field_name, model_cls)
        for field_name in field_names
    }


def normalize_field_name_to_db(field_name, model_cls):
    """
    Normalize a field name to its database column name.

    For FK fields referenced by relationship name, returns the attname (e.g., 'business' -> 'business_id')
    For regular fields, returns as-is.

    Args:
        field_name: Field name (can be 'business' or 'business_id')
        model_cls: Model class

    Returns:
        Database column name
    """
    try:
        field = model_cls._meta.get_field(field_name)
        if isinstance(field, ForeignKey):
            return field.attname  # Returns 'business_id' for 'business' field
        return field_name
    except Exception:  # noqa: BLE001
        return field_name