from flask import Blueprint, request, jsonify
from tinydb import Query
from api.utils import get_validated_user_id, send_event_for_current_user
from api.error_codes import ErrorCodes
from db.db import child_db, task_db, reward_db
from db.child_overrides import (
    insert_override,
    get_override,
    get_overrides_for_child,
    delete_override
)
from models.child_override import ChildOverride
from events.types.event import Event
from events.types.event_types import EventType
from events.types.child_override_set import ChildOverrideSetPayload
from events.types.child_override_deleted import ChildOverrideDeletedPayload
import logging

child_override_api = Blueprint('child_override_api', __name__)
logger = logging.getLogger(__name__)


@child_override_api.route('/child/<child_id>/override', methods=['PUT'])
def set_child_override(child_id):
    """
    Set or update a custom value for a task/reward for a specific child.
    """
    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': ErrorCodes.UNAUTHORIZED}), 401
    
    # Validate child exists and belongs to user
    ChildQuery = Query()
    child_result = child_db.search((ChildQuery.id == child_id) & (ChildQuery.user_id == user_id))
    if not child_result:
        return jsonify({'error': 'Child not found', 'code': ErrorCodes.CHILD_NOT_FOUND}), 404
    
    child_dict = child_result[0]
    
    # Parse request data
    data = request.get_json() or {}
    entity_id = data.get('entity_id')
    entity_type = data.get('entity_type')
    custom_value = data.get('custom_value')
    
    # Validate required fields
    if not entity_id:
        return jsonify({'error': 'entity_id is required', 'code': ErrorCodes.MISSING_FIELD, 'field': 'entity_id'}), 400
    if not entity_type:
        return jsonify({'error': 'entity_type is required', 'code': ErrorCodes.MISSING_FIELD, 'field': 'entity_type'}), 400
    if custom_value is None:
        return jsonify({'error': 'custom_value is required', 'code': ErrorCodes.MISSING_FIELD, 'field': 'custom_value'}), 400
    
    # Validate entity_type
    if entity_type not in ['task', 'reward']:
        return jsonify({'error': 'entity_type must be "task" or "reward"', 'code': ErrorCodes.INVALID_VALUE, 'field': 'entity_type'}), 400
    
    # Validate custom_value range
    if not isinstance(custom_value, int) or custom_value < 0 or custom_value > 10000:
        return jsonify({'error': 'custom_value must be an integer between 0 and 10000', 'code': ErrorCodes.INVALID_VALUE, 'field': 'custom_value'}), 400
    
    # Validate entity exists and is assigned to child
    if entity_type == 'task':
        EntityQuery = Query()
        entity_result = task_db.search(
            (EntityQuery.id == entity_id) &
            ((EntityQuery.user_id == user_id) | (EntityQuery.user_id == None))
        )
        if not entity_result:
            return jsonify({'error': 'Task not found', 'code': ErrorCodes.TASK_NOT_FOUND}), 404
        
        # Check if task is assigned to child
        assigned_tasks = child_dict.get('tasks', [])
        if entity_id not in assigned_tasks:
            return jsonify({'error': 'Task not assigned to child', 'code': ErrorCodes.ENTITY_NOT_ASSIGNED}), 404
    
    else:  # reward
        EntityQuery = Query()
        entity_result = reward_db.search(
            (EntityQuery.id == entity_id) &
            ((EntityQuery.user_id == user_id) | (EntityQuery.user_id == None))
        )
        if not entity_result:
            return jsonify({'error': 'Reward not found', 'code': ErrorCodes.REWARD_NOT_FOUND}), 404
        
        # Check if reward is assigned to child
        assigned_rewards = child_dict.get('rewards', [])
        if entity_id not in assigned_rewards:
            return jsonify({'error': 'Reward not assigned to child', 'code': ErrorCodes.ENTITY_NOT_ASSIGNED}), 404
    
    # Create and insert override
    try:
        override = ChildOverride.create_override(
            child_id=child_id,
            entity_id=entity_id,
            entity_type=entity_type,
            custom_value=custom_value
        )
        insert_override(override)
        
        # Send SSE event
        resp = send_event_for_current_user(
            Event(EventType.CHILD_OVERRIDE_SET.value, ChildOverrideSetPayload(override))
        )
        if resp:
            return resp
        
        return jsonify({'override': override.to_dict()}), 200
    
    except ValueError as e:
        return jsonify({'error': str(e), 'code': ErrorCodes.VALIDATION_ERROR}), 400
    except Exception as e:
        logger.error(f"Error setting override: {e}")
        return jsonify({'error': 'Internal server error', 'code': ErrorCodes.INTERNAL_ERROR}), 500


@child_override_api.route('/child/<child_id>/overrides', methods=['GET'])
def get_child_overrides(child_id):
    """
    Get all overrides for a specific child.
    """
    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': ErrorCodes.UNAUTHORIZED}), 401
    
    # Validate child exists and belongs to user
    ChildQuery = Query()
    child_result = child_db.search((ChildQuery.id == child_id) & (ChildQuery.user_id == user_id))
    if not child_result:
        return jsonify({'error': 'Child not found', 'code': ErrorCodes.CHILD_NOT_FOUND}), 404
    
    # Get all overrides for child
    overrides = get_overrides_for_child(child_id)
    
    return jsonify({'overrides': [o.to_dict() for o in overrides]}), 200


@child_override_api.route('/child/<child_id>/override/<entity_id>', methods=['DELETE'])
def delete_child_override(child_id, entity_id):
    """
    Delete an override (reset to default).
    """
    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': ErrorCodes.UNAUTHORIZED}), 401
    
    # Validate child exists and belongs to user
    ChildQuery = Query()
    child_result = child_db.search((ChildQuery.id == child_id) & (ChildQuery.user_id == user_id))
    if not child_result:
        return jsonify({'error': 'Child not found', 'code': ErrorCodes.CHILD_NOT_FOUND}), 404
    
    # Get override to determine entity_type for event
    override = get_override(child_id, entity_id)
    if not override:
        return jsonify({'error': 'Override not found', 'code': ErrorCodes.OVERRIDE_NOT_FOUND}), 404
    
    entity_type = override.entity_type
    
    # Delete override
    deleted = delete_override(child_id, entity_id)
    if not deleted:
        return jsonify({'error': 'Override not found', 'code': ErrorCodes.OVERRIDE_NOT_FOUND}), 404
    
    # Send SSE event
    resp = send_event_for_current_user(
        Event(EventType.CHILD_OVERRIDE_DELETED.value, 
              ChildOverrideDeletedPayload(child_id, entity_id, entity_type))
    )
    if resp:
        return resp
    
    return jsonify({'message': 'Override deleted'}), 200
