# coding=utf-8
import traceback
import json

from _mysql_exceptions import IntegrityError
from django.db.models import ProtectedError, Q, Sum
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from django.db import transaction, IntegrityError
from apps.account.decorators import token_required, permission_required
from apps.account.models import Department, User
from apps.base import Formater
from apps.foundation.models import BizLog, Option
from apps.goods.models import Goods
from apps.plan.filters import ProductionPlanFilter, SalePlanFilter
from apps.plan.models import ProductionPlan, SalePlan, ProductionPlanDetail, SalePlanDetail
from apps.plan.resources import ProductionPlanResource, SalePlanResource, SalePlanDetailResource, ProductionPlanDetailResource
from apps.plan.serializers import ProductionPlanSerializer, ProductionPlanDetailSerializer, SalePlanSerializer, \
    SalePlanDetailSerializer

from libs.http import JSONResponse, JSONError, DataGridJSONResponse
from libs import utils
from apps.exceptions import CustomError, ExportChange
from django.conf import settings


@csrf_exempt
@permission_required('plan.view_production_plan')
def production_list(request):
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = ProductionPlan.objects.filter(Q(create_user_id__in=user_ids) | Q(department_id__in=department_ids) | Q(create_user=request.user))
    f = ProductionPlanFilter(request.GET, queryset=rows)
    total_row = f.qs.aggregate(total_count=Sum('total_count'))
    more = {
        'total_count': Formater.formatCountShow(total_row['total_count'])
    }
    rows, total = utils.get_page_data(request, f.qs)
    serializer = ProductionPlanSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total, more)

@csrf_exempt
@permission_required('plan.export_production_plan')
def production_export(request):
    id = request.GET.get('id')
    if id:
        production = ProductionPlan.getById(id)
        goods_rows = ProductionPlanDetail.objects.filter(production__id=production.id)
        serializer = ProductionPlanDetailSerializer(goods_rows, many=True)
        export_data = ExportChange.dict_to_obj(serializer)
        export_data = ProductionPlanDetailResource().export(export_data)
        filename = utils.attachment_save(export_data)
        BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出生产计划明细")
        return JSONResponse({'filename': filename})

    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = ProductionPlan.objects.filter(Q(create_user_id__in=user_ids) | Q(department_id__in=department_ids) | Q(create_user=request.user))
    f = ProductionPlanFilter(request.GET, queryset=rows)
    serializer = ProductionPlanSerializer(f.qs, many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    export_data = ProductionPlanResource().export(export_data)
    filename = utils.attachment_save(export_data)
    BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出生产计划")
    return JSONResponse({'filename': filename})

@csrf_exempt
@permission_required('plan.add_production_plan')
def production_save(request):
    id = request.GET.get('id')
    goods_data = json.loads(request.POST.get('items'))
    production_data = json.loads(request.POST.get('production'))
    try:
        with transaction.atomic():
            pb = ProductionPlanSerializer.factory(request.user, production_data, id)
            if pb.instance and pb.instance.status == settings.PASS:
                raise CustomError(u'审核通过,禁止修改')
            pb = pb.validSave()
            ProductionPlanDetail.objects.filter(production=pb).delete()
            for good_data in goods_data:
                good_data['production'] = pb.id
                good_data['product'] = good_data['id']
                if 'product_time' in good_data and not good_data['product_time']:
                    good_data['product_time'] = None
                production = ProductionPlanDetailSerializer.factory(request.user, data=good_data)
                production.validSave()
            pb.updateTotalCount()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败！')
    return JSONResponse()

@csrf_exempt
@permission_required('plan.check_production_plan')
def production_check(request):
    id = request.GET.get('id')
    c_type = request.GET.get('c_type')
    status = int(request.GET.get('status'))
    try:
        with transaction.atomic():
            production = ProductionPlan.getById(id)
            if c_type == 'check':
                # 审核
                if status == settings.PASS:
                    if production.status == settings.CHECKING:
                        raise CustomError(u'该生产计划已审核')
                    production.status = settings.CHECKING
                    production.check_user = request.user
                    production.check_time = timezone.now()
                    BizLog.objects.addnew(
                        request.user,
                        BizLog.CHECK,
                        u"审核生产计划[%s]，id=%d" % (production.name, production.id),
                    )
                else:
                    if production.status == settings.DEFAULT:
                        raise CustomError(u'该生产计划未审核')
                    if production.check_user2:
                        raise CustomError(u'该生产计划已复核')
                    production.status = settings.DEFAULT
                    production.check_user = None
                    production.check_time = None
                    BizLog.objects.addnew(
                        request.user,
                        BizLog.CHECK,
                        u"取消审核生产计划[%s]，id=%d" % (production.name, production.id),
                    )
            elif c_type == 'check2':
                #复核
                if status == settings.PASS:
                    if production.status == settings.DEFAULT:
                        raise CustomError(u'该生产计划未审核')
                    if production.check_user3:
                        raise CustomError(u'该生产计划已批准')

                    production.check_user2 = request.user
                    production.check_time2 = timezone.now()
                    BizLog.objects.addnew(
                        request.user,
                        BizLog.CHECK,
                         u"复核生产计划[%s]，id=%d" % (production.name, production.id),
                    )
                else:
                    if not production.check_user2:
                        raise CustomError(u'该生产计划未复核')
                    if production.check_user3:
                        raise CustomError(u'该生产计划已批准')

                    production.check_user2 = None
                    production.check_time2 = None
                    BizLog.objects.addnew(
                        request.user,
                        BizLog.CHECK,
                         u"取消复核生产计划[%s]，id=%d" % (production.name, production.id),
                    )
            elif c_type == 'check3':
                #批准
                if status == settings.PASS:
                    if not production.check_user2:
                        raise CustomError(u'该生产计划未复核')
                    if production.check_user3:
                        raise CustomError(u'该生产计划已批准')
                    production.status = status
                    production.check_user3 = request.user
                    production.check_time3 = timezone.now()
                    BizLog.objects.addnew(
                        request.user,
                        BizLog.CHECK,
                        u"批准生产计划[%s]，id=%d" % (production.name, production.id),
                    )
                else:
                    if not production.check_user3:
                        raise CustomError(u'该生产计划未批准')

                    production.status = settings.CHECKING
                    production.check_user3 = None
                    production.check_time3 = None
                    BizLog.objects.addnew(
                        request.user,
                        BizLog.CHECK,
                        u"撤消批准生产计划[%s]，id=%d" % (production.name, production.id),
                    )
            production.save()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'审核失败')
    return JSONResponse({})

@csrf_exempt
@permission_required('plan.delete_production_plan')
def production_delete(request):
    id = int(request.GET.get('id'))
    try:
        with transaction.atomic():
            production = ProductionPlan.getById(id)
            if production.status == settings.PASS:
                raise CustomError(u'该生产计划已审核,禁止删除')
            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除生产计划[%s]，id=%d" % (production.name, production.id))
            ProductionPlanDetail.objects.filter(production__id=production.id).delete()
            production.delete()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except ProtectedError:
        return JSONError(u'该计划已被引用,禁止删除')
    except IntegrityError:
        return JSONError(u'该计划已被引用,禁止删除')
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'删除失败！')

    return JSONResponse({})

@csrf_exempt
@permission_required('plan.view_production_plan')
def production_detail(request):
    id = request.GET.get('id')
    production = ProductionPlan.getById(id)
    company = production.department.getCompany()
    goods_rows = ProductionPlanDetail.objects.filter(production__id=production.id)
    data = {
        'production': [],
        'goods_items': []
    }
    if production.status == settings.PASS:
        status_text = u'已审核'
    else:
        status_text = u'待审核'
    production_item = {
        'id': production.id,
        'name': production.name,
        'company': company.name,
        'no': production.no,
        'total_count': Formater.formatCountShow(production.total_count),
        'status': production.status,
        'status_text': status_text,
        'notes': production.notes,
        'create_user': production.create_user.name,
        'check_user': production.check_user and production.check_user.name or '',
        'check_time': Formater.formatStrTime(production.check_time),
        'check_user2': production.check_user2 and production.check_user2.name or '',
        'check_time2': Formater.formatStrTime(production.check_time2),
        'check_user3': production.check_user3 and production.check_user3.name or '',
        'check_time3': Formater.formatStrTime(production.check_time3),
        'create_time': Formater.formatStrTime(production.create_time),
    }
    data['production'].append(production_item)
    for row in goods_rows:
        item = {
            'id': row.id,
            'goods_id': row.product.id,
            'name': row.product.product_base.name,
            'model': row.product.product_base.model,
            'unit': row.product.product_base.unit,
            'quality_request_id': row.quality_request and row.quality_request.id,
            'quality_request_text': row.quality_request and row.quality_request.name or '',
            'count': Formater.formatCountShow(row.count),
            'product_user_id': row.product_user and row.product_user.id,
            'product_user_text': row.product_user and row.product_user.name or '',
            'p_department_id': row.p_department and row.p_department.id,
            'p_department_text': row.p_department and row.p_department.name or '',
            'product_time': Formater.formatStrDate(row.product_time),
            'notes': row.notes or ''
        }
        data['goods_items'].append(item)
    return JSONResponse(data)

@csrf_exempt
@token_required
def plan_options(request):
    departments = Department.objects.filter().values('id', 'name')
    users = User.objects.filter(status=User.INSERVICE).values('id', 'name', 'department__name')
    data = {
        'users': [],
        'departments': [],
    }
    for row in users:
        data['users'].append(
            {'id':row['id'], 'name':row['name'], 'department_name':row['department__name']}
        )
    for row in departments:
        data['departments'].append(
            {'id':row['id'], 'name':row['name']}
        )
    return JSONResponse(data)

@csrf_exempt
@permission_required('plan.view_sale_plan')
def sale_list(request):
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = SalePlan.objects.filter(Q(create_user_id__in=user_ids) | Q(department_id__in=department_ids) | Q(create_user=request.user))
    f = SalePlanFilter(request.GET, queryset=rows)
    total_row = f.qs.aggregate(total_count=Sum('total_count'), total_amount=Sum('total_amount'))
    more = {
        'total_count' : Formater.formatCountShow(total_row['total_count']),
        'total_amount' : Formater.formatAmountShow(total_row['total_amount'])
    }
    rows, total = utils.get_page_data(request, f.qs)
    serializer = SalePlanSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total, more)


@csrf_exempt
@permission_required('plan.add_sale_plan')
def sale_save(request):
    source = request.GET.get('source')
    id = request.GET.get('id')
    # detail_id:添加保存，销售计划直接保存，不需要添加明细detail_id=-1，添加明细保存默认detail_id=0，修改保存，detail_id=明细id
    detail_id = -1
    if source == 'touch':
        goods_data = json.loads(request.body)['item']
        sale_data = json.loads(request.body)['main']
        detail_id = json.loads(request.body)['detail']
    else:
        goods_data = json.loads(request.POST.get('goods'))
        sale_data = json.loads(request.POST.get('sale'))
    try:
        with transaction.atomic():
            serializer = SalePlanSerializer.factory(request.user, sale_data, id)
            if serializer.instance and serializer.instance.status == settings.PASS:
                raise CustomError(u'该销售计划已审核，禁止修改！')
            serializer = serializer.validSave()
            if source == 'touch' and detail_id >= 0:
                # 手机端保存，如果是修改，先删除要修改的明细
                SalePlanDetail.objects.filter(id=int(detail_id)).delete()
                for item in goods_data:
                    amount = Formater.formatPrice(item['price'])*Formater.formatCount(item['require_count']) if item['price'] else 0
                    require_time = item['require_time'] and item['require_time'].split('T')[0] or None
                    instance = SalePlanDetail.objects.create(
                        main_id=id,
                        goods_id=item['goods'],
                        quality_request_id=item['quality_request'],
                        require_count=Formater.formatCount(item['require_count']),
                        require_time=require_time,
                        amount=amount,
                        price=Formater.formatPrice(item['price'] or 0),
                    )
                    BizLog.objects.addnew(
                        request.user,
                        BizLog.INSERT,
                         u"添加销售计划明细[%s]，id=%d" % (instance.goods, instance.id),
                        item
                    )
            else:
                SalePlanDetail.objects.filter(main=serializer).delete()

                for good_data in goods_data:
                    good_data['main'] = serializer.id
                    if 'require_time' in good_data and not good_data['require_time']:
                        good_data['require_time'] = None
                    detail_serializer = SalePlanDetailSerializer.factory(request.user, data=good_data)
                    detail_serializer.validSave()
            serializer.update_total()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败！')

    return JSONResponse(serializer.id)

@csrf_exempt
@permission_required('plan.delete_sale_plan')
def sale_delete(request):
    id = int(request.GET.get('id'))
    try:
        with transaction.atomic():
            sale_plan = SalePlan.getById(id)
            if sale_plan.status == settings.PASS:
                raise CustomError(u'该销售计划已审核，禁止删除！')

            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除销售计划[%s]，id=%d" % (sale_plan.no, sale_plan.id))
            SalePlanDetail.objects.filter(main=sale_plan).delete()
            sale_plan.delete()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except ProtectedError:
        return JSONError(u'该销售计划已被引用，禁止删除！')
    except IntegrityError:
        return JSONError(u'该销售计划已被引用，禁止删除！')
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'删除失败！')

    return JSONResponse({})

@csrf_exempt
@permission_required('plan.view_sale_plan')
def sale_detail(request):
    id = request.GET.get('id')
    sale_plan = SalePlan.getById(id)
    if sale_plan.status == settings.PASS:
        check_status = u'已审核'
    else:
        check_status = u'待审核'
    company = sale_plan.department.getCompany()
    sale_data = {
        'id': sale_plan.id,
        'no': sale_plan.no,
        'company': company.name,
        'total_count': Formater.formatCountShow(sale_plan.total_count),
        'total_amount': Formater.formatAmountShow(sale_plan.total_amount),
        'name': sale_plan.customer.name,
        'mobile': sale_plan.customer.mobile,
        'customer_id': sale_plan.customer.id,
        'company_name': sale_plan.customer.company_name or '',
        'credit_code': sale_plan.customer.credit_code or '',
        'company_tel': sale_plan.customer.company_tel or '',
        'address': sale_plan.customer.address or '',
        'status': check_status,
        'status_id': sale_plan.status,
        'check_user': sale_plan.check_user and sale_plan.check_user.name or '',
        'create_user': sale_plan.create_user and sale_plan.create_user.name or '',
        'check_time':sale_plan.check_time and Formater.formatStrTime(sale_plan.check_time) or '',
        'create_time': Formater.formatStrTime(sale_plan.create_time),
        'notes': sale_plan.notes or '',
    }

    data = {
        'goods_items': [],
        'sale_data': sale_data
    }
    is_toproduction = False
    goods_rows = SalePlanDetail.objects.filter(main=sale_plan)
    for row in goods_rows:
        require_product_count = 0
        if row.require_count > row.goods.product_base.stock_count:
            require_product_count = row.require_count-row.goods.product_base.stock_count
            is_toproduction = True
        item = {
            'detail_id': row.id,
            'id': row.id,
            'goods_id': row.goods.id,
            'name': row.goods.product_base.name,
            'model': row.goods.product_base.model,
            'unit': row.goods.product_base.unit,
            'quality_request': row.quality_request and row.quality_request.id or None,
            'quality_request_text':row.quality_request and row.quality_request.name or '',
            'require_count': Formater.formatCountShow(row.require_count),
            'price': Formater.formatEmptyPriceShow(row.price),
            'require_time': Formater.formatStrDate(row.require_time),
            'current_stock_count': Formater.formatCountShow(row.goods.product_base.stock_count),
            'require_product_count': Formater.formatCountShow(require_product_count),
        }
        data['goods_items'].append(item)
    data['sale_data']['is_toproduction'] = is_toproduction
    return JSONResponse(data)

@csrf_exempt
@permission_required('plan.check_sale_plan')
def sale_check(request):
    id = request.GET.get('id')
    status = int(request.GET.get('status'))
    try:
        with transaction.atomic():
            sale_plan = SalePlan.getById(id)
            if status == settings.PASS:
                if sale_plan.status == settings.PASS:
                    raise CustomError(u'该销售计划已审核')
                sale_plan.status = status
                sale_plan.check_user = request.user
                sale_plan.check_time = timezone.now()
                BizLog.objects.addnew(
                    request.user,
                    BizLog.CHECK,
                    u"审核销售计划[%s]，id=%d" % (sale_plan.no, sale_plan.id),
                )
            else:
                if sale_plan.status == settings.DEFAULT:
                    raise CustomError(u'该销售计划未审核')
                sale_plan.status = status
                sale_plan.check_user = None
                sale_plan.check_time = None
                BizLog.objects.addnew(
                    request.user,
                    BizLog.CHECK,
                    u"取消审核销售计划[%s]，id=%d" % (sale_plan.no, sale_plan.id),
                )
            sale_plan.save()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'审核失败')
    return JSONResponse({})

@csrf_exempt
@permission_required('plan.export_sale_plan')
def sale_export_detail(request):
    id = request.GET.get('id')
    sale_plan = SalePlan.getById(id)
    sale_plan_detail = SalePlanDetail.objects.filter(main=sale_plan)
    serializer = SalePlanDetailSerializer(sale_plan_detail, many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    export_data = SalePlanDetailResource().export(export_data)
    filename = utils.attachment_save(export_data)
    BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出销售计划[%s]明细" % (serializer.no))
    return JSONResponse({'filename': filename})


@csrf_exempt
@permission_required('plan.export_sale_plan')
def sale_export(request):
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = SalePlan.objects.filter(
        Q(create_user_id__in=user_ids) | Q(department_id__in=department_ids) | Q(create_user=request.user))
    f = SalePlanFilter(request.GET, queryset=rows)
    serializer = SalePlanSerializer(f.qs, many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    export_data = SalePlanResource().export(export_data)
    filename = utils.attachment_save(export_data)
    BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出销售计划")
    return JSONResponse({'filename': filename})