from flask import Blueprint, request, jsonify
from tinydb import Query

from api.utils import get_validated_user_id, send_event_for_current_user
from db.db import routine_db
from db.routine_items import add_item, delete_item, get_item, get_items_for_routine, update_item
from events.types.event import Event
from events.types.event_types import EventType
from events.types.routine_modified import RoutineModified
from models.routine_item import RoutineItem

routine_item_api = Blueprint('routine_item_api', __name__)


def _validate_routine_owned_by_user(routine_id: str, user_id: str):
    q = Query()
    return routine_db.get((q.id == routine_id) & ((q.user_id == user_id) | (q.user_id == None)))


@routine_item_api.route('/routine/<routine_id>/item/add', methods=['PUT'])
def add_routine_item(routine_id):
    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': 'UNAUTHORIZED'}), 401

    routine = _validate_routine_owned_by_user(routine_id, user_id)
    if not routine:
        return jsonify({'error': 'Routine not found'}), 404

    data = request.get_json() or {}
    name = data.get('name', '').strip()
    image_id = data.get('image_id')

    if not name:
        return jsonify({'error': 'name is required'}), 400

    existing_items = get_items_for_routine(routine_id)
    order = data.get('order', len(existing_items))

    item = RoutineItem(routine_id=routine_id, name=name, image_id=image_id, order=order)
    add_item(item)

    send_event_for_current_user(
        Event(EventType.ROUTINE_MODIFIED.value, RoutineModified(routine_id, RoutineModified.OPERATION_EDIT))
    )
    return jsonify(item.to_dict()), 201


@routine_item_api.route('/routine/<routine_id>/item/<item_id>/edit', methods=['PUT'])
def edit_routine_item(routine_id, item_id):
    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': 'UNAUTHORIZED'}), 401

    routine = _validate_routine_owned_by_user(routine_id, user_id)
    if not routine:
        return jsonify({'error': 'Routine not found'}), 404

    existing = get_item(item_id)
    if not existing or existing.routine_id != routine_id:
        return jsonify({'error': 'Item not found'}), 404

    data = request.get_json(force=True) or {}
    is_dirty = False

    if 'name' in data:
        name = data.get('name', '').strip()
        if not name:
            return jsonify({'error': 'name cannot be empty'}), 400
        existing.name = name
        is_dirty = True

    if 'image_id' in data:
        existing.image_id = data.get('image_id')
        is_dirty = True

    if 'order' in data:
        order = data.get('order')
        if not isinstance(order, int) or order < 0:
            return jsonify({'error': 'order must be a non-negative integer'}), 400
        existing.order = order
        is_dirty = True

    if not is_dirty:
        return jsonify({'error': 'No valid fields to update'}), 400

    update_item(existing)
    send_event_for_current_user(
        Event(EventType.ROUTINE_MODIFIED.value, RoutineModified(routine_id, RoutineModified.OPERATION_EDIT))
    )
    return jsonify(existing.to_dict()), 200


@routine_item_api.route('/routine/<routine_id>/item/<item_id>', methods=['DELETE'])
def delete_routine_item(routine_id, item_id):
    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': 'UNAUTHORIZED'}), 401

    routine = _validate_routine_owned_by_user(routine_id, user_id)
    if not routine:
        return jsonify({'error': 'Routine not found'}), 404

    item = get_item(item_id)
    if not item or item.routine_id != routine_id:
        return jsonify({'error': 'Item not found'}), 404

    delete_item(item_id)
    send_event_for_current_user(
        Event(EventType.ROUTINE_MODIFIED.value, RoutineModified(routine_id, RoutineModified.OPERATION_EDIT))
    )
    return jsonify({'message': 'Item deleted'}), 200


@routine_item_api.route('/routine/<routine_id>/items', methods=['GET'])
def list_routine_items(routine_id):
    user_id = get_validated_user_id()
    if not user_id:
        return jsonify({'error': 'Unauthorized', 'code': 'UNAUTHORIZED'}), 401

    routine = _validate_routine_owned_by_user(routine_id, user_id)
    if not routine:
        return jsonify({'error': 'Routine not found'}), 404

    items = [item.to_dict() for item in get_items_for_routine(routine_id)]
    return jsonify({'items': items, 'count': len(items)}), 200
