# coding: utf-8
import math
from multiprocessing import cpu_count
from threading import Thread

from django.core.management import BaseCommand
from django.db.models import Q

from api.models.message import Conversation, ConversationUserStatus
from message.utils.conversation import get_conversation_head_bulk_action
from message.utils.es_abstract import get_esop
from message.utils.es import tzlc


def get_conversations(year, month):
    q = Q(last_reply_time__year=year)
    if month:
        q &= Q(last_reply_time__month=month)
    conversations = Conversation.objects.filter(q)
    return conversations

class Command(BaseCommand):

    def __init__(self, *args, **kwargs):
        super(Command, self).__init__(*args, **kwargs)
        self.esop = get_esop()

    def add_arguments(self, parser):
        parser.add_argument('-y', help="sync year; default 2019", type=int, default=2019)
        parser.add_argument('-m', help="sync month; default 0", type=int, default=0)

    def handle(self, *args, **options):
        year = options['y']
        month = options['m']
        count = get_conversations(year, month).count()
        thread_nums = cpu_count()

        step = int(math.ceil((float(count) / thread_nums)))
        threads = []
        for i, start in enumerate(range(0, count, step)):
            end = min(count, start + step)
            t = Thread(target=self.update, args=(start, end, year, month), name=i + 1)
            threads.append(t)
            t.start()

        for t in threads:
            t.join()

    def update(self, start, end, year, month):
 
        def get_user_last_name(user_status):
            from api.models.user import User
            try:
                return User.objects.get(id=user_status.user_id).last_name
            except:
                return ''

        conversations = get_conversations(year, month)[start: end]
        conv_headers = {}
        for conversation in conversations.iterator():
            conv_headers[conversation.id] = {
                'id': conversation.id,
                'last_reply_time': tzlc(conversation.last_reply_time),
                'is_star_by_doctor': conversation.user_status_set.filter(is_star=True).exists(),
                'conversation_type': conversation.conversation_type,
                'users': [{
                    'id': user_status.user_id,
                    'last_name': get_user_last_name(user_status),
                    'is_unread': user_status.read_status,
                    'comment': user_status.comment,
                    'status': True if user_status.status == '1' else False
                } for user_status in conversation.user_status_set.all()],
            }
            # if conv_id not in conv_headers:
            #     conv_headers[conv_id] = {
            #         'id': conv_id,
            #         'users':[{
            #             'id':conv_status.user_id,
            #             'last_name':get_user_last_name(conv_status),
            #             'is_unread':conv_status.read_status,
            #             'comment': conv_status.comment,
            #             'status': True if conv_status.status == '1' else False
            #         }],
            #         'last_reply_time':tzlc(conv_status.last_reply_time),
            #         'is_star_by_doctor':conv_status.is_star,
            #     }
            # else:
            #     conv_headers[conv_id]['users'].append({
            #         'id':conv_status.user_id,
            #         'last_name':get_user_last_name(conv_status),
            #         'is_unread':conv_status.read_status,
            #         'comment': conv_status.comment,
            #         'status': True if conv_status.status == '1' else False
            #     })
            #     if conv_status.is_star:
            #         conv_headers[conv_id]['is_star_by_doctor'] = True
            print(conversation.id)
        conv_headers = conv_headers.values()
        actions = map(get_conversation_head_bulk_action, conv_headers)
        print self.esop.helper_bulk(actions, request_timeout=100)
