# coding=utf-8

import time
import json

from django.conf import settings
from django.utils.html import escape

from api.models import Feedback
from api.models import FeedbackCategory
from api.models import FeedbackMessage
from api.models import FeedbackImage
from api.models import FEEDBACK_MESSAGE_TYPE
from api.models import FEEDBACK_RELATED_OBJECT_TYPE
from api.models import User, Person
from api.models import Order

from api.tool.datetime_tool import get_timestamp, get_timestamp_or_none
from api.tool.user_tool import get_user_from_context, get_user_extra_by_user_id
from api.tool.image_utils import get_full_path

from rpc.tool.error_code import CODES, gen
from rpc.tool.log_tool import logging_exception
from rpc.tool.protocol import PushUrlProtocol
from rpc.decorators import bind, bind_context
from rpc.decorators import list_interface
from rpc.cache import feedback_msg_cache

from gm_types.push import PUSH_INFO_TYPE


@bind_context('api/feedcategory/list')
def get_feed_category_list(ctx):
    feedcategorys = FeedbackCategory.objects.filter(enabled=True).order_by('position')
    result = []
    for fc in feedcategorys:
        result.append({
            'id': fc.id,
            'description': fc.description,
            'icon': fc.icon,
            'title': fc.title,
        })
    return result


@bind_context('api/feedbackcategory/get', login_required=True)
def get_feedback_categoty(ctx, id):
    user = get_user_from_context(ctx)
    user_extra = get_user_extra_by_user_id(user.id)
    fb_category = FeedbackCategory.objects.get(id=id)
    result = {}
    if fb_category:
        result['phone'] = user_extra.phone
        result['id'] = fb_category.id
        result['show_order_input'] = False
        if FEEDBACK_RELATED_OBJECT_TYPE.ORDER == fb_category.related_type:
            result['show_order_input'] = True
    return result


@bind_context('api/feedback/history', login_required=True)
@list_interface(offset_name='start_num', limit_name="count", element_model=Feedback)
def get_feedback_history(ctx, start_num=0, count=10):
    """
    :Function 反馈历史（列表）
    :param ctx:
    :return:
    """
    user = get_user_from_context(ctx)
    feedback = Feedback.objects.filter(user=user).order_by('-id')

    messages = []
    for fb in feedback[start_num:start_num+count]:
        redis_key = '{0}:{1}'.format(user.id, fb.id)

        ret = feedback_msg_cache.get(redis_key)

        if not ret:
            unread = False
        else:
            unread = True

        messages.append({
            "id": fb.id,
            "title": fb.feedbackcategory and fb.feedbackcategory.title or u'问题反馈',
            "content": escape(fb.content),
            "unread": unread
        })

    return messages


@bind_context('api/feedback/conversation_reply', login_required=True)
def conversation_reply(ctx, feedback_id, message_type, message):
    """
    :function 发送反馈回复
    :param ctx:
    :param start_num:
    :param limit:
    :return:
    """
    # validate messge_type
    if not message_type in (FEEDBACK_MESSAGE_TYPE.TXT, FEEDBACK_MESSAGE_TYPE.IMAGE):
        return gen(CODES.PARAMS_INCOMPLETE)

    user = get_user_from_context(ctx)
    try:
        feedback = Feedback.objects.get(id=feedback_id)
        if feedback.user != user:
            raise Feedback.DoesNotExist
    except Feedback.DoesNotExist:
        return gen(CODES.FEEDBACK_NOT_FOUND)

    message = escape(message)
    feedback_message = FeedbackMessage.objects.create(feedback=feedback,
                                                      person=user.person,
                                                      message_type=message_type,
                                                      message=message)
    feedback.has_more_asks = True
    feedback.save()
    return feedback_message.id


@bind_context('api/feedback/conversation_detail', login_required=True)
def get_conversation_detail(ctx, feedback_id, count=10):
    """
    :function 反馈详情对话列表接口, 返回最近的count条数据
    :param ctx:
    :return:
    """
    user = get_user_from_context(ctx)

    try:
        feedback = Feedback.objects.get(id=feedback_id)
        if feedback.user != user:
            raise Feedback.DoesNotExist
    except Feedback.DoesNotExist:
        return gen(CODES.FEEDBACK_NOT_FOUND)

    feedback_messages = FeedbackMessage.objects.filter(feedback=feedback)

    messages = []

    total = feedback_messages.count()
    count = min(total, count)

    for msg in feedback_messages[total-count:]:
        portait = uid = None

        try:
            uid = msg.servant.user.id
            portrait = get_full_path(settings.GENGMEI_CUSTOMER_SERVICES_PORTRAIT)
        except:
            pass

        if not uid:
            uid = msg.person.user.id
            ue = get_user_extra_by_user_id(uid)
            portrait = get_full_path(ue.portrait) or get_full_path(u'img%2Fuser_portrait.png')

        messages.append({
                'portrait': portrait,
                'uid': uid,
                'message': escape(msg.message),
                'message_type': msg.message_type,
                'created_time': get_timestamp_or_none(msg.created_time)
        })

    order_id, order_name = '', ''

    if feedback.related_id:
        if feedback.feedbackcategory.related_type == FEEDBACK_RELATED_OBJECT_TYPE.ORDER:
            try:
                order = Order.objects.get(pk=feedback.related_id)
                order_id = feedback.related_id
                service_snapshot = json.loads(order.service_snapshot)
                order_name = service_snapshot['name']
            except:
                logging_exception()

    images = [ret.image_url for ret in feedback.images.all() if ret]

    feedback_content = feedback.content and feedback.content.strip() or ''
    ue = get_user_extra_by_user_id(feedback.user.id)
    result = {
        'feedback': {
            'id': feedback.id,
            'content': escape(feedback_content),
            'order_id': order_id,
            'order_name': order_name,
            'images': images,
            'uid': feedback.user.id,
            'portrait': get_full_path(ue.portrait) or get_full_path(u'img%2Fuser_portrait.png'),
            'created_time': get_timestamp_or_none(feedback.created_time),
        },
        'messages': messages
    }

    redis_key = '{0}:{1}'.format(user.id,feedback_id)
    feedback_msg_cache.delete(redis_key)
    return result


@bind_context('api/feedback/create', login_required=True)
def feedback_create(ctx, id, content, phone=None, qq=None, images=[], relate_id=None):
    """
    :Function 递交反馈信息
    :param ctx:
    :param id:
    :param content:
    :param phone:
    :param qq:
    :param images:
    :param relate_id:
    :return:
    """
    user = get_user_from_context(ctx)
    feedbackcategory =FeedbackCategory.objects.get(id=id)
    feedback = Feedback()

    feedback.user = user
    feedback.feedbackcategory = feedbackcategory

    if content:
        content = escape(content)
        feedback.content = content

    if phone:
        feedback.phone = phone

    if qq:
        feedback.qq = qq

    if relate_id:
        feedback.related_id = relate_id

    redis_key = 'create_check:{0}'.format(user.id) # redis_key 缓存用户反馈
    ret = feedback_msg_cache.get(redis_key)

    task_info = {
        'user_id':user.id,
        'content':content,
        'phone':phone,
        'qq':qq,
        'relate_id':relate_id,
    }
    if ret:
        ret = json.loads(ret)
        if ret == task_info:
            return gen(CODES.FEEDBACK_REPETITION)

    feedback_msg_cache.setex(redis_key,6,json.dumps(task_info))# expire in 6s

    feedback.save()

    for image in images:
        fb_image = FeedbackImage()
        fb_image.feedback = feedback
        fb_image.image_url = image
        fb_image.save()

    return {'feedback_id': feedback.id}


@bind_context('api/feedback/reply_status', login_required=True)
def conversation_reply_status(ctx, feedback_id):
    """NOTE: this api is only used internally
    :Function 添加一个这个反馈是否已经被客服回复过
    :param ctx:
    :param feedback_id:
    :return:
    """
    try:
        feedback = Feedback.objects.get(id=feedback_id)
    except Feedback.DoesNotExist:
        return gen(CODES.FEEDBACK_NOT_FOUND)

    # set reply status flag
    redis_key = '{0}:{1}'.format(feedback.user.id, feedback_id)
    ret = feedback_msg_cache.set(redis_key, 1)

    return gen(CODES.SUCCESS)

@bind_context('api/feedback/category/get_by_title', login_required=False)
def get_feedback_category_by_title(ctx, title):

    try:
        feedback = FeedbackCategory.objects.get(title=title)
    except FeedbackCategory.DoesNotExist:
        return gen(CODES.FEEDBACK_NOT_FOUND)

    result = {
        'id': feedback.id,
        'title': feedback.title,
    }
    return result
