# coding=utf-8
import json
import math

from django.db import IntegrityError
from django.db import transaction

from gm_types.gaia import ORDER_SOURCE, ORDER_STATUS
from rpc.tool.generate_random_code import generate_num
from rpc.tool.error_code import gen, CODES
from maidan.models import MaidanOrder, MaidanOrderSnapshot, MaidanPayment

from pay.tool import random_tool


class IDGenerator(object):
    def _get_timestamp(self):
        import time
        return int(time.time() * 1000)

    def generate(self):
        import struct
        import random
        now = self._get_timestamp()
        series_id = random.randrange(0, 1 << 22)
        high = now >> 10
        low = (now & 0xffc00000) | series_id
        return struct.pack(">II", high, low)


def _create_order_record(maidan_name,
                         tag_names,
                         maidan_price_cent,
                         doctor_discount_rate,
                         doctor_discount_cent,
                         gengmei_offers_rate,
                         gengmei_offers_cent,
                         discount_rate,
                         discount_cent,
                         source,
                         payment_cent,
                         user,
                         doctor,
                         settle_price_cent):

    with transaction.atomic():
        maidan_order_id = None
        order = None
        payment_id = ""

        while True:
            try:
                order_id = random_tool.generate_id(id_length=12)
                order = MaidanOrder.objects.create(
                    id=order_id,
                    maidan_name=maidan_name,
                    tag_names=tag_names,
                    status=ORDER_STATUS.NOT_PAID,
                    maidan_price_cent=maidan_price_cent,
                    payment_cent=payment_cent,
                    payment_id=payment_id,
                    user=user,
                    source=source,
                    doctor=doctor,
                    doctor_discount_rate=doctor_discount_rate,
                    doctor_discount_cent=doctor_discount_cent,
                    gengmei_offers_rate=gengmei_offers_rate,
                    gengmei_offers_cent=gengmei_offers_cent,
                    discount_cent=discount_cent,
                    settle_price_cent=settle_price_cent,
                )
                maidan_order_id = order_id
                break
            except IntegrityError:
                pass

        while True:
            try:
                generator = IDGenerator()
                new_payment_id = generator.generate().encode('hex').upper()
                payment = MaidanPayment.objects.create(
                    id=new_payment_id,
                    name=maidan_name,
                    total_amount_cent=payment_cent,
                    maidan_order_id=maidan_order_id,
                )
                payment_id = new_payment_id
                break
            except IntegrityError:
                pass

        order.payment_id = payment_id
        order.save()

        MaidanOrderSnapshot.objects.create(
            maidan_order=order,
            maidan_name=maidan_name,
            tag_names=tag_names,
            doctor_portrait=doctor.portrait,
            maidan_price_cent=maidan_price_cent,
            user=user,
            source=source,
            doctor=doctor,
            doctor_discount_rate=doctor_discount_rate,
            doctor_discount_cent=doctor_discount_cent,
            gengmei_offers_rate=gengmei_offers_rate,
            gengmei_offers_cent=gengmei_offers_cent,
            discount_rate=discount_rate,
            hospital=doctor.hospital,
            business_partner=doctor.business_partener,
        )

    return maidan_order_id


def create_order(user, doctor, tags, maidan_price, source=ORDER_SOURCE.UNKNOW):

    maidan_settings = doctor.maidansetting
    if not maidan_settings.is_open:
        gen(CODES.MAIDAN_NOT_OPEN)

    tags_str = "+".join(tags)
    maidan_name = u'【{}@{}】{}'.format(doctor.hospital.city.name, doctor.name, tags_str)
    tag_names = json.dumps(tags)
    maidan_price_cent = maidan_price * 100

    doctor_discount_rate = maidan_settings.doctor_discount_rate
    doctor_discount_cent = maidan_price_cent * doctor_discount_rate / 100

    gengmei_offers_rate = maidan_settings.gengmei_offers_rate
    gengmei_offers_cent = maidan_price_cent * gengmei_offers_rate / 100

    discount_rate = maidan_settings.discount_rate
    payment_cent = int(math.ceil((doctor_discount_cent - gengmei_offers_cent)/100.0)) * 100

    settle_price_cent = int(doctor_discount_cent * (100 - discount_rate)/10000.0) * 100
    discount_cent = payment_cent - settle_price_cent

    order_id = _create_order_record(maidan_name=maidan_name,
                                    tag_names=tag_names,
                                    maidan_price_cent=maidan_price_cent,
                                    doctor_discount_rate=doctor_discount_rate,
                                    doctor_discount_cent=doctor_discount_cent,
                                    gengmei_offers_rate=gengmei_offers_rate,
                                    gengmei_offers_cent=gengmei_offers_cent,
                                    discount_cent=discount_cent,
                                    discount_rate=discount_rate,
                                    source=source,
                                    payment_cent=payment_cent,
                                    user=user,
                                    doctor=doctor,
                                    settle_price_cent=settle_price_cent)
    return order_id
