# coding=utf-8
from __future__ import unicode_literals, print_function, absolute_import

from django.conf import settings
from django.core.management import BaseCommand
from django.db import transaction

from api.models import Message, Conversation, ConversationUserStatus
from message.utils.es_abstract import get_esop, ESBulkAction
from message.utils.es_abstract import table_conversation, table_message
from message.utils.conversation import get_conversation_head_bulk_action
from message.utils.db import tzlc
from datetime import datetime


class Command(BaseCommand):
    def add_arguments(self, parser):
        parser.add_argument('--msg-ids', help='list of message ids to be removed',
                            nargs='+', type=int, dest='msg_ids')

    def handle(self, *args, **options):
        msg_ids = options['msg_ids']
        assert msg_ids is not None
        with transaction.atomic():
            # lock messages
            messages = Message.objects.select_for_update().filter(pk__in=msg_ids)
            msg_ids = []
            conversation_ids = set()
            for message in messages:
                conversation_ids.add(message.conversation_id)
                msg_ids.append(message.id)
            conversation_ids = list(conversation_ids)

            # lock conversations
            conversations = Conversation.objects.select_for_update().filter(pk__in=conversation_ids)
            # lock conversation user status
            conversation_user_status = ConversationUserStatus.objects.select_for_update()\
                .filter(conversation_id__in=conversation_ids)

            # remove messages in MySQL
            Message.objects.filter(pk__in=msg_ids).delete()

            # remove messages in elasticsearch
            def get_remove_msg_bulk_action(msg_id):
                return ESBulkAction(
                    table=table_message,
                    params={
                        '_op_type':'delete',
                        '_id': msg_id,
                    }
                )
            esop = get_esop()
            actions = map(get_remove_msg_bulk_action, msg_ids)
            esop.helper_bulk(actions)

            # renew conversation and conversation user status in MySQL
            for conversation in conversations:
                try:
                    # get last msg from MySQL
                    last_msg = conversation.message_set.latest('id')
                    last_reply_time = last_msg.send_time
                    last_msg_content_disp = Message.content_display(
                        type=last_msg.type,
                        content=last_msg.content,
                        user=last_msg.user)

                    # update conversation
                    conversation.last_reply_time = last_reply_time
                    conversation.last_msg_content_disp = last_msg_content_disp
                    conversation.save()

                    # update conversation user status
                    ConversationUserStatus.objects.filter(conversation=conversation).update(
                        last_reply_time=last_reply_time)
                except Message.DoesNotExist:
                    conversation.last_reply_time = datetime.utcfromtimestamp(0)
                    conversation.last_msg_content_disp = ''
                    conversation.save()
                    ConversationUserStatus.objects.filter(conversation=conversation).update(
                        last_reply_time=datetime.utcfromtimestamp(0),
                        is_empty=True)

            # sync with elasticsearch
            conv_ids = list(conversations.values_list('id', flat=True))
            # get messages from es conversation
            es_messages = esop.mget(table=table_conversation, body={
                'ids':[str(conv_id) for conv_id in conv_ids]
            })
            es_messages = {
                m['_source']['id']: m['_source']['messages'] for m in es_messages['docs']
            }
            conv_headers = {}
            for conv in conversations:
                conv_id = int(conv.id)
                # user status information
                conv_headers[conv_id] = {
                    'id': conv_id,
                    'last_reply_time':tzlc(conv.last_reply_time),
                }
                # message information
                conv_headers[conv_id]['messages'] = []
                if conv_id in es_messages:
                    for m in es_messages[conv_id]:
                        if m['id'] not in msg_ids:
                            conv_headers[conv_id]['messages'].append(m)

            conv_headers = conv_headers.values()
            actions = map(get_conversation_head_bulk_action, conv_headers)
            esop.helper_bulk(actions)
