# coding=utf-8

import json

from django.core.management import BaseCommand

from answer.models import Question, Answer, AnswerReply
from api.models import (
    DeviceRecord, User, CouponInfo, Order, Diary, Problem, TopicReply,
    PrivateConversation, Feedback
)
from api.models.others import UserBlackList
from api.tool.image_utils import get_full_path
from rpc.context import get_rpc_remote_invoker
from social.models import UserFollow
from statistic.models import Device
from talos.models import ReplyCollect


class Command(BaseCommand):
    remote_rpc_client = get_rpc_remote_invoker()

    def add_arguments(self, parser):
        parser.add_argument('-s', action='store', dest='start', type=int, default=0)
        parser.add_argument('-c', action='store', dest='count', type=int, default=10)

    def handle(self, *args, **options):
        start, count = options['start'], options['count']
        if start < 0 or count < 0:
            print('start=%s, count=%s' % (start, count))
            assert False

        data = []
        for user in User.objects.all()[start:start + count]:
            result = {
                'device': self.get_devices(user),
                'user': self.get_users(user),
                'behavior': self.get_behaviors(user),
                'content': self.get_contents(user),
            }
            data.append(result)

        if data:
            file_name = "feature_engineering_user_%s-%s.json" % (start, start + count - 1)
            self.store_to_json(data, file_name)

        print("finished!")

    @classmethod
    def store_to_json(cls, data=[], file_name="feature_engineering.json"):
        try:
            with open(file_name, 'w') as f:
                f.write(json.dumps(data, indent=4))
        except IOError as e:
            print(e)
            raise

    @classmethod
    def get_devices(cls, user):
        device_record = get_device_records(user=user)
        device_static = get_device_static(user=user)
        black_list = UserBlackList.objects.filter(bind_user=user)

        device_msg = {
            "device_id": device_record['device_id'],
            "model": device_static['model'],
            "app_version": device_static['app_version'],
            "os_version": device_static['os_version'],
            "device_type": device_static['device_type'],
            "device_related_user": device_record['device_id'],      # TODO: same as device_id?
            "device_id_in_blacklist": [q.device.device_id for q in black_list if q.device],
            "create_time": [t.strftime("%Y-%m-%d %H:%M:%S") for t in device_record['create_time']]
        }

        return device_msg

    @classmethod
    def get_users(cls, user):
        user_msg = {
            "name": user.userextra.name,
            "username": user.username,
            "portrait": get_full_path(user.userextra.portrait),
            "country": user.person.area.area_name if user.person.area else '',
            "city": user.userextra.city.name if user.userextra.city else '',
            "email": user.person.email,
            "phone": user.userextra.phone,
            "platform": user.person.platform,
            "is_puppet": user.person.is_puppet,
            "login_type": user.userextra.auth_type,
            "follower": UserFollow.objects.filter(follow=user, bond=True).count(),
            "following": UserFollow.objects.filter(user=user, bond=True).count(),
        }

        return user_msg

    @classmethod
    def get_behaviors(cls, user):
        diary_msg = get_diary_msg(user)
        private_msg = get_private_msg(user)
        question_answer_msg = get_question_answer_msg(user)

        behavior_msg = {
            "points": user.userextra.points_amount,     # 美分，从person.points 中取, 该脚本已弃用 20180103
            "coupon": CouponInfo.objects.filter(user=user).count(),
            "order": Order.objects.filter(user=user, validated=True).count(),
            "diary": {
                "diary": diary_msg['diary'],
                "legal_diary": diary_msg['legal_diary'],
                "illegal_diary": diary_msg['illegal_diary'],
                "topic": diary_msg['topic'],
                "topic_reply_sent": diary_msg['topic_reply_sent'],
                "topic_reply_recv": diary_msg['topic_reply_recv'],
            },
            "question": {
                "question": question_answer_msg['question'],
                "answer_sent": question_answer_msg['answer_sent'],
                "answer_recv": question_answer_msg['answer_recv'],
                "answer_reply_sent": question_answer_msg['answer_reply_sent'],
                "answer_reply_recv": question_answer_msg['answer_reply_recv'],
            },
            "private_msg": {
                "private_msg_sent": private_msg['private_msg_sent'],
                "private_msg_recv": private_msg['private_msg_recv'],
            },
            "feedback": Feedback.objects.filter(user=user).count(),
        }

        return behavior_msg

    @classmethod
    def get_contents(cls, user):
        content_msg = get_content_msg(user)

        return {
            "question": content_msg['question'],
            "answer": content_msg['answer'],
            "answer_reply": content_msg['answer_reply'],
            "diary": content_msg['diary'],
            "topic": content_msg['topic'],
            "topic_reply": content_msg['topic_reply'],
            "private_msg": content_msg['private_msg'],
        }


def get_device_records(user):
    query_set = DeviceRecord.objects.filter(user=user).values('device_id', 'created_time')

    return {
        'device_id': [q['device_id'] for q in query_set],
        'create_time': [q['created_time'] for q in query_set]
    }


def get_device_static(user):
    query_set = Device.objects.filter(user=user).values('model', 'version', 'os_version', 'platform')

    return {
        'model': [q['model'] for q in query_set],
        'app_version': [q['version'] for q in query_set],
        'os_version': [q['os_version'] for q in query_set],
        'device_type': [q['platform'] for q in query_set]
    }


def get_diary_msg(user):
    diary_set = Diary.objects.filter(user=user, is_online=True)

    return {
        'diary': [q.id for q in diary_set],
        'legal_diary': [q.id for q in diary_set if not q.is_spam],
        'illegal_diary': [q.id for q in diary_set if q.is_spam],
        'topic': [q.topic_num for q in diary_set],
        'topic_reply_sent': ReplyCollect.objects.filter(reply_user_id=user.id).count(),
        'topic_reply_recv': ReplyCollect.objects.filter(user_id=user.id).count(),
    }


def get_private_msg(user):
    return {
        'private_msg_sent': PrivateConversation.objects.filter(user=user).count(),
        'private_msg_recv': PrivateConversation.objects.filter(target_user=user).count(),
    }


def get_question_answer_msg(user):
    question_set = list(Question.objects.filter(user=user.id, is_online=True).values_list('id', flat=True))
    answer_set = list(Answer.objects.filter(user=user.id, is_online=True).values_list('id', flat=True))

    return {
        'question': len(question_set),
        'answer_sent': len(answer_set),
        'answer_recv': Answer.objects.filter(question_id__in=question_set, is_online=True).count(),
        'answer_reply_sent': AnswerReply.objects.filter(user=user.id, is_online=True).count(),
        'answer_reply_recv': AnswerReply.objects.filter(answer_id__in=answer_set, is_online=True).count(),
    }


def get_content_msg(user):
    question_set = Question.objects.filter(user=user.id, is_online=True).values('id', 'content')
    question_contents = [q['content'] for q in question_set]

    answer_set = Answer.objects.filter(user=user.id, is_online=True).values('id', 'content')
    answer_contents = [q['content'] for q in answer_set]

    answer_reply_set = AnswerReply.objects.filter(user=user.id, is_online=True).values('id', 'content')
    answer_reply_contents = [q['content'] for q in answer_reply_set]

    diary_set = Diary.objects.filter(user=user, is_online=True).values('id', 'title')
    diary_titles = [q['title'] for q in diary_set]
    diary_ids = [q['id'] for q in diary_set]

    topic_set = Problem.objects.filter(diary_id__in=diary_ids, is_online=True).values('id', 'answer')
    topic_content = [q['answer'] for q in topic_set]

    topic_reply_set = list(TopicReply.objects.filter(user=user, is_online=True).values_list('content', flat=True))

    private_msg_set = list(PrivateConversation.objects.filter(user=user).values_list('text', flat=True))

    return {
        'question': ''.join(question_contents),
        'answer': ''.join(answer_contents),
        'answer_reply': ''.join(answer_reply_contents),
        'diary': ''.join(diary_titles),
        'topic': ''.join(topic_content),
        'topic_reply': ''.join(topic_reply_set),
        'private_msg': ''.join(private_msg_set)
    }