"""
SBCC Message Feedback Management Functions

Simple functions for managing SBCC message feedback via the API.
"""

import requests
from typing import Optional, Dict, Any, List

from .config import get_base_path, get_headers
from .exceptions import APIError


def _handle_response(response: requests.Response) -> Dict[str, Any]:
    """Handle API response and raise appropriate errors."""
    try:
        response.raise_for_status()
        # Handle 204 No Content responses
        if response.status_code == 204:
            return {}
        # Handle empty responses
        if not response.content:
            return {}
        return response.json()
    except requests.exceptions.HTTPError as e:
        error_msg = "Unknown error"
        try:
            error_data = response.json()
            error_msg = error_data.get('error', str(e))
        except:
            error_msg = response.text or str(e)
        raise APIError(f"API request failed: {error_msg}", response.status_code)
    except requests.exceptions.JSONDecodeError:
        raise APIError(f"Invalid JSON response: {response.text}", response.status_code)
    except requests.exceptions.RequestException as e:
        raise APIError(f"Request failed: {str(e)}", None)


def list_message_feedbacks(filters: Optional[Dict[str, Any]] = None) -> List[Dict[str, Any]]:
    """
    List all SBCC message feedbacks with optional filtering.
    
    Args:
        filters: Optional dictionary containing filter parameters:
            - form_guid: Filter by form GUID
            - user_guid: Filter by user GUID
            - practice: Filter by practice (partial match)
            - barrier: Filter by barrier (partial match)
            - is_liked: Filter by liked status (True/False)
    
    Returns:
        List of message feedback dictionaries
    
    Raises:
        APIError: If the API request fails
        ValueError: If configuration is not set
    """
    url = f"{get_base_path()}/message-feedback/"
    params = {}
    
    if filters:
        if 'form_guid' in filters:
            params['form_guid'] = filters['form_guid']
        if 'user_guid' in filters:
            params['user_guid'] = filters['user_guid']
        if 'practice' in filters:
            params['practice'] = filters['practice']
        if 'barrier' in filters:
            params['barrier'] = filters['barrier']
        if 'is_liked' in filters and filters['is_liked'] is not None:
            params['is_liked'] = str(filters['is_liked']).lower()
    
    response = requests.get(url, headers=get_headers(), params=params)
    return _handle_response(response)


def get_message_feedback(pk: int) -> Dict[str, Any]:
    """
    Get a single SBCC message feedback by ID.
    
    Args:
        pk: Primary key (ID) of the message feedback
    
    Returns:
        Message feedback dictionary
    
    Raises:
        APIError: If the API request fails or feedback not found
        ValueError: If configuration is not set
    """
    url = f"{get_base_path()}/message-feedback/{pk}/"
    response = requests.get(url, headers=get_headers())
    return _handle_response(response)


def create_message_feedback(feedback_data: Dict[str, Any]) -> Dict[str, Any]:
    """
    Create a new SBCC message feedback.
    
    Args:
        feedback_data: Dictionary containing:
            - form_guid: Form GUID (required)
            - user_guid: User GUID (required)
            - practice: Practice name (required)
            - barrier: Barrier description (required)
            - generated_message: Generated message text (required)
            - is_liked: Whether the message is liked (optional, default: False)
            - preferred_message: Preferred message text (optional, default: empty string)
            - test_mode: If True, request will be in test mode (optional, default: False)
    
    Returns:
        Created message feedback dictionary
    
    Raises:
        APIError: If the API request fails
        ValueError: If configuration is not set or required keys missing
    """
    required_keys = ['form_guid', 'user_guid', 'practice', 'barrier', 'generated_message']
    missing_keys = [key for key in required_keys if key not in feedback_data]
    if missing_keys:
        raise ValueError(f"Missing required keys in feedback_data: {missing_keys}")
    
    url = f"{get_base_path()}/message-feedback/"
    payload = {
        'form_guid': feedback_data['form_guid'],
        'user_guid': feedback_data['user_guid'],
        'practice': feedback_data['practice'],
        'barrier': feedback_data['barrier'],
        'generated_message': feedback_data['generated_message'],
        'is_liked': feedback_data.get('is_liked', False),
        'preferred_message': feedback_data.get('preferred_message', ''),
    }
    
    test_mode = feedback_data.get('test_mode', False)
    response = requests.post(url, headers=get_headers(test_mode=test_mode), json=payload)
    return _handle_response(response)


def update_message_feedback(pk: int, feedback_data: Dict[str, Any]) -> Dict[str, Any]:
    """
    Update all fields of an SBCC message feedback (PUT request).
    
    Args:
        pk: Primary key (ID) of the message feedback
        feedback_data: Dictionary containing:
            - form_guid: Form GUID (required)
            - user_guid: User GUID (required)
            - practice: Practice name (required)
            - barrier: Barrier description (required)
            - generated_message: Generated message text (required)
            - is_liked: Whether the message is liked (required)
            - preferred_message: Preferred message text (optional, default: empty string)
            - test_mode: If True, request will be in test mode (optional, default: False)
    
    Returns:
        Updated message feedback dictionary
    
    Raises:
        APIError: If the API request fails
        ValueError: If configuration is not set or required keys missing
    """
    required_keys = ['form_guid', 'user_guid', 'practice', 'barrier', 'generated_message', 'is_liked']
    missing_keys = [key for key in required_keys if key not in feedback_data]
    if missing_keys:
        raise ValueError(f"Missing required keys in feedback_data: {missing_keys}")
    
    url = f"{get_base_path()}/message-feedback/{pk}/"
    payload = {
        'form_guid': feedback_data['form_guid'],
        'user_guid': feedback_data['user_guid'],
        'practice': feedback_data['practice'],
        'barrier': feedback_data['barrier'],
        'generated_message': feedback_data['generated_message'],
        'is_liked': feedback_data['is_liked'],
        'preferred_message': feedback_data.get('preferred_message', ''),
    }
    
    test_mode = feedback_data.get('test_mode', False)
    response = requests.put(url, headers=get_headers(test_mode=test_mode), json=payload)
    return _handle_response(response)


def partial_update_message_feedback(pk: int, feedback_data: Dict[str, Any]) -> Dict[str, Any]:
    """
    Partially update an SBCC message feedback (PATCH request).
    
    Args:
        pk: Primary key (ID) of the message feedback
        feedback_data: Dictionary containing optional update fields:
            - form_guid: Form GUID (optional)
            - user_guid: User GUID (optional)
            - practice: Practice name (optional)
            - barrier: Barrier description (optional)
            - generated_message: Generated message text (optional)
            - is_liked: Whether the message is liked (optional)
            - preferred_message: Preferred message text (optional)
            - test_mode: If True, request will be in test mode (optional, default: False)
    
    Returns:
        Updated message feedback dictionary
    
    Raises:
        APIError: If the API request fails
        ValueError: If configuration is not set
    """
    url = f"{get_base_path()}/message-feedback/{pk}/"
    payload = {}
    
    if 'form_guid' in feedback_data:
        payload['form_guid'] = feedback_data['form_guid']
    if 'user_guid' in feedback_data:
        payload['user_guid'] = feedback_data['user_guid']
    if 'practice' in feedback_data:
        payload['practice'] = feedback_data['practice']
    if 'barrier' in feedback_data:
        payload['barrier'] = feedback_data['barrier']
    if 'generated_message' in feedback_data:
        payload['generated_message'] = feedback_data['generated_message']
    if 'is_liked' in feedback_data:
        payload['is_liked'] = feedback_data['is_liked']
    if 'preferred_message' in feedback_data:
        payload['preferred_message'] = feedback_data['preferred_message']
    
    test_mode = feedback_data.get('test_mode', False)
    response = requests.patch(url, headers=get_headers(test_mode=test_mode), json=payload)
    return _handle_response(response)


def delete_message_feedback(pk: int, test_mode: bool = False) -> None:
    """
    Delete an SBCC message feedback.
    
    Args:
        pk: Primary key (ID) of the message feedback
        test_mode: If True, request will be in test mode (not persisted)
    
    Raises:
        APIError: If the API request fails or feedback not found
        ValueError: If configuration is not set
    """
    url = f"{get_base_path()}/message-feedback/{pk}/"
    response = requests.delete(url, headers=get_headers(test_mode=test_mode))
    _handle_response(response)
