# coding=utf-8
# create by oldman at 17/1/4
import pipes
import sys
import traceback

from django.core.management import BaseCommand
from django.db import transaction
from gm_types.gaia import ACTIVITY_TYPE_ENUM

from api.models import SpecialItem, SKUPriceRule, ServiceItemPrice, Special


class Command(BaseCommand):
    """
    迁移specialitem的价格数据到skuprice这张表
    python manage.py update_20170104_async_specialitem_price
    create by oldman at 2017-01-04
    """

    def add_arguments(self, parser):
        parser.add_argument('--id-start', type=int)
        parser.add_argument('--id-end', type=int)
        parser.add_argument('--make-slices', type=int, default=None)

    def handle(self, *args, **options):
        make_slices = options.get('make_slices')
        if make_slices is not None:
            slices = self.get_slices(make_slices)
            for start, end in slices:
                cmdline = list(sys.argv)
                idx = cmdline.index('--make-slices')
                assert idx >= 0
                cmdline = cmdline[:idx]
                if start is not None:
                    cmdline.extend([
                        '--id-start', str(start),
                    ])
                if end is not None:
                    cmdline.extend([
                        '--id-end', str(end),
                    ])
                print(' '.join(pipes.quote(s) for s in cmdline))
        else:
            id_start = options.get('id_start')
            id_end = options.get('id_end')
            self.handle_range(id_start=id_start, id_end=id_end)

    def get_slices(self, count):
        expected_max_id = 400000
        sep_points = [None]
        for p in range(1, count):
            sep_points.append(int(expected_max_id / count * p))
        sep_points.append(None)
        return zip(sep_points[:count], sep_points[1:])

    def handle_range(self, id_start=None, id_end=None):
        qs = SpecialItem.objects.all().filter(serviceitem__isnull=False)

        if id_start is not None:
            qs = qs.filter(id__gte=id_start)
        if id_end is not None:
            qs = qs.filter(id__lt=id_end)

        specialitems = qs.order_by('id')

        aid_2_at_and_ruleid = {int(x[1]): (x[2], x[0]) for x in
                               SKUPriceRule.objects.all().values_list('id', 'activity_id', 'activity_type')}
        spid_2_is_seckill = {x['id']: x['is_seckill'] for x in Special.objects.all().values('id', 'is_seckill')}
        siid_2_default_price = {x['service_item_id']: x for x in
                                ServiceItemPrice.objects.filter(is_default_price=True).values('service_item_id'
                                                                                              , 'original_price',
                                                                                              'cash_back_rate',
                                                                                              'cash_back_fee',
                                                                                              'self_support_discount',
                                                                                              'discount',
                                                                                              'pre_payment_price',
                                                                                              'gengmei_price')}

        count = specialitems.count()

        import datetime
        log_name_base = "sku161212_async_special_item" + datetime.datetime.now().strftime('%Y%m%d_%H%M%S_%f')
        log_error_name = log_name_base + '_error.log'
        log_name = log_name_base + '_info.log'

        with open(log_error_name, 'a+') as error_log_file:
            with open(log_name, 'a+') as log_file:

                header_text = "range : [{}, {})\ncount : {}".format(id_start, id_end, count)
                print header_text

                log_file.write(header_text)
                log_file.write('\n')

                begin = 0
                step = 1000

                while begin <= count:

                    print "on index {}/{}".format(begin, count)

                    for item in specialitems[begin:begin + step]:
                        try:
                            with transaction.atomic():
                                rule_info_id = None
                                special_is_seckill = None

                                if (item.special_id in aid_2_at_and_ruleid) and (item.special_id in spid_2_is_seckill):
                                    activity_type = aid_2_at_and_ruleid[item.special_id][0]
                                    special_is_seckill = spid_2_is_seckill[item.special_id]
                                    target_type = ACTIVITY_TYPE_ENUM.SECKILL if special_is_seckill else ACTIVITY_TYPE_ENUM.SPECIAL
                                    if activity_type == target_type:
                                        rule_info_id = aid_2_at_and_ruleid[item.special_id][1]

                                if rule_info_id is None:
                                    raise ValueError(
                                        u'get specialitem priceRule error, specialitem_id :' + str(item.id))

                                if special_is_seckill is False:

                                    try:
                                        price_info, is_create = ServiceItemPrice.objects.get_or_create(
                                            service_item_id=item.serviceitem_id,
                                            selling_rule_id=rule_info_id
                                        )
                                        if is_create:
                                            price_info.is_enable = True
                                            serviceitem_price_info = siid_2_default_price[item.serviceitem_id]
                                            price_info.original_price = serviceitem_price_info.get('original_price', 0)
                                            price_info.cash_back_rate = serviceitem_price_info.get('cash_back_rate', 0)
                                            price_info.cash_back_fee = serviceitem_price_info.get('cash_back_fee', 0)
                                            price_info.self_support_discount = \
                                                serviceitem_price_info.get('self_support_discount', 0)
                                            if item.doctorseckillapply:
                                                price_info.discount = item.doctorseckillapply.commission
                                                price_info.pre_payment_price = item.doctorseckillapply.pre_payment_price
                                                price_info.gengmei_price = item.doctorseckillapply.seckill_price
                                                price_info.sale_limit = item.doctorseckillapply.available_num
                                            else:
                                                price_info.discount = serviceitem_price_info.get('discount', 0)
                                                price_info.pre_payment_price = serviceitem_price_info.get(
                                                    'pre_payment_price', 0)
                                                price_info.gengmei_price = serviceitem_price_info.get('gengmei_price',
                                                                                                      0)

                                            price_info.save()

                                        log_text = "item.id: " + str(item.id) + " is_create: " + str(is_create)

                                        log_file.write(log_text)
                                        log_file.write('\n')
                                    except Exception:
                                        raise ValueError('save price info error')

                        except Exception:
                            error_text = traceback.format_exc()

                            error_log_file.write(error_text)
                            error_log_file.write('\n')

                            continue

                    begin += step

                print "success!"

                log_file.write("success!")
                log_file.write('\n')
