#coding=utf-8

import traceback
import json

from collections import OrderedDict
from django.db import transaction,IntegrityError
from django.db.models import F,ProtectedError
from django.shortcuts import get_object_or_404
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.models import Permission, Group
from django.utils import timezone
from libs import utils
from libs.utils import dump_form_errors
from libs.http import JSONError, JSONResponse,DataGridJSONResponse
from apps.dashboard.forms import MyAuthenticationForm
from decorators import token_required,permission_required
from apps.exceptions import CustomError

from apps.foundation.models import BizLog

from models import User, Department,SubDepartment,SubEmployee
from serializers import EmployeeSerializer, EmployeeSafeSerializer, GroupSerializer,GroupComboboxSerializer

from django.db.models import Q
from django.conf import settings
from apps.goods.models import GoodsGodownEntry
from apps.material.models import Deliver
from apps.order.models import SaleOrder, GoodsDeliver
from apps.plan.models import SalePlan, ProductionPlan
from apps.purchase.models import PurchasePlan, PurchaseOrder, GodownEntry, GodownEntryReturn
from apps.warehouse.models import Warehouse, Inventory
from apps.office.models import Notice,NoticeBrowseRecord

@csrf_exempt
def login(request):
    form = MyAuthenticationForm(data=request.POST, request=request)
    if form.is_valid():
        user = form.get_user()
        if user.status == User.DIMISSION:
            BizLog.objects.addnew(user, BizLog.INSERT, u"离职账号[%s]登录,IP[%s]" % (
                user.username,
                request.META['REMOTE_ADDR']
            ))
            return JSONError(u'离职账号禁止登录')

        permissions = list(user.get_all_permissions())

        BizLog.objects.addnew(user, BizLog.INSERT, u"[%s]登录,IP[%s]" % (
            user.username,
            request.META['REMOTE_ADDR']
        ))

        return JSONResponse({
            'user_id':user.id,
            'access_token':form.access_token,
            'name':user.name,
            'permissions':permissions
        })
    else:
        BizLog.objects.addnew(None, BizLog.INSERT, u"[%s]登录失败,密码[%s],IP[%s]" % (
            request.POST['username'],
            request.POST['password'],
            request.META['REMOTE_ADDR']
        ))
        return JSONError(dump_form_errors(form))

@permission_required('foundation.view_group')
def group_list(request):
    rows = Group.objects.filter()

    rows, total = utils.get_page_data(request, rows)
    serializer = GroupSerializer(rows, many=True)

    return DataGridJSONResponse(serializer.data, total)

@token_required
def group_combobox_list(request):
    rows = Group.objects.filter()

    total = rows.count()
    #rows, total = utils.get_page_data(request, rows)
    serializer = GroupComboboxSerializer(rows, many=True)

    return DataGridJSONResponse(serializer.data, total)

@csrf_exempt
@permission_required('foundation.add_group')
def group_save(request):
    id = request.GET.get('id')
    data = json.loads(request.body)

    try:
        with transaction.atomic():
            User.objects.save_group(id, data['name'], data['permissions'], request.user)
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败')
    return JSONResponse()

@csrf_exempt
@permission_required('foundation.delete_group')
def group_delete(request):
    id = request.GET.get('id')

    try:
        with transaction.atomic():
            group = Group.objects.filter(pk=id).first()
            if not group:
                raise CustomError(u'未找到相应的权限组')
            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除权限组[%s],id=%s" % (group.name, id))
            group.delete()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except ProtectedError:
        return JSONError(u'该权限组已分配给用户，禁止删除！')
    except IntegrityError:
        return JSONError(u'该权限组已分配给用户，禁止删除！')
    except:
        traceback.print_exc()
        return JSONError(u'删除失败')
    return JSONResponse()

@token_required
def permission_all(request):
    rows = Permission.objects.all().exclude(name__startswith='Can')
    rows = User.objects.sort_perms(rows)

    menus = OrderedDict()
    for row in rows:
        item = {'id': row.id, 'name': row.name}
        mn = User.objects.get_menuname_of_contenttype(row.content_type.app_label, row.content_type.model)
        if menus.has_key(mn):
            permissions = menus[mn]
        else:
            permissions = menus[mn] = OrderedDict()

        if permissions.has_key(row.content_type.name):
            if not item in permissions[row.content_type.name]:
                permissions[row.content_type.name].append(item)
        else:
            permissions[row.content_type.name] = [item, ]
    return JSONResponse(menus)

@permission_required('account.view_user')
def employee_list(request):
    username = request.GET.get('username')
    name = request.GET.get('name')

    rows = User.objects.filter()
    if username:
        rows = rows.filter(username__icontains=username)
    if name:
        rows = rows.filter(name__icontains=name)
    rows, total = utils.get_page_data(request, rows)
    serializer = EmployeeSafeSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total)

@csrf_exempt
@permission_required('account.add_user')
def employee_save(request):
    id = request.GET.get('id')
    data = json.loads(request.body)

    try:
        with transaction.atomic():
            serializer = EmployeeSerializer.factory(request.user, data, id)
            if serializer.instance:
                user = serializer.instance
                if not data['password']:
                    data['password'] = user.password
                else:
                    user.set_password(data['password'])
                    data['password'] = user.password
            serializer.validSave()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败')
    return JSONResponse()

@csrf_exempt
@token_required
def employee_tree(request):
    def child_employee_tree(department_id,children):
        rows = User.objects.filter(department_id=department_id)
        for row in rows:
            item = {
                'id': row.id,
                'value': 'employee_' + str(row.id),
                'name': row.name
            }
            children.append(item)

    def child_department_tree(parent_id,children):
        rows = Department.objects.filter(parent_id=parent_id)
        for row in rows:
            item = {
                'id': row.id,
                'value': 'department_' + str(row.id),
                'name': row.name,
                'children': []
            }
            child_employee_tree(row.id,item['children'])
            child_department_tree(row.id,item['children'])
            children.append(item)

    result = []
    child_department_tree(None,result)
    return JSONResponse(result)

@csrf_exempt
@permission_required('account.add_user')
def manager_save(request):
    id = request.GET.get('id')
    data = json.loads(request.body)
    try:
        with transaction.atomic():
            user = User.getById(id)
            user.removeSubs()

            for row in data['managers']:
                sub_arr = row.split('_')
                if sub_arr[0] == 'department':
                    SubDepartment.objects.create(user=user,department_id=int(sub_arr[1]))
                elif sub_arr[0] == 'employee':
                    SubEmployee.objects.create(user=user,employee_id=int(sub_arr[1]))
            BizLog.objects.addnew(request.user, BizLog.UPDATE, u"修改员工管理范围[%s],id=%s" % (user.name, user.id),data)
        return JSONResponse({})
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception,e:
        traceback.print_exc()
        return JSONError(u'保存失败')

@csrf_exempt
@permission_required('account.delete_user')
def employee_delete(request):
    id = request.GET.get('id')
    try:
        with transaction.atomic():
            user = User.getById(id)
            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除员工[%s],id=%d" % (user.name, user.id))
            user.removeSubs()
            user.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({})

@token_required
def employee_combobox_list(request):
    rows = User.objects.filter(status=User.INSERVICE)
    total = rows.count()
    #rows, total = utils.get_page_data(request, rows)
    serializer = EmployeeSafeSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total)

@token_required
def employee_list_mobile(request):
    id = request.GET.get('id')
    user = User.objects.filter(id=id).first()
    data = {
        'name': user.name,
        'tel': user.tel,
        'department_name': user.department.name
    }
    return JSONResponse(data)

@csrf_exempt
@token_required
def password_save(request):
    data = json.loads(request.body)
    try:
        data['new_password'] = data['new_password'].strip(u' ')
        data['confirm_password'] = data['confirm_password'].strip(u' ')
        data['old_password'] = data['old_password'].strip(u' ')

        if data['new_password'] != data['confirm_password']:
            raise CustomError(u'两次输入的密码不一致， 请检查')

        with transaction.atomic():
            if not request.user.check_password(data['old_password']):
                raise CustomError(u'原密码输入错误， 请检查')
            request.user.set_password(data['new_password'])
            request.user.save()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败！')
    return JSONResponse()

@permission_required('account.view_department')
def department_list(request):
    result = []
    rows = Department.objects.filter()
    for row in rows:
        isCompany = False
        if row.id == row.company_id:
            isCompany = True
        item = {
            'id': row.id,
            'company': row.company_id,
            'product_range': row.product_range,
            'product_range_text': row.product_range and Department.PRODUCT_RANGE_CHOICES[row.product_range - 1][1] or '',
            'name': row.name,
            'notes': row.notes,
            'isCompany': isCompany,
            'parent_id': row.parent_id or 0,
        }
        result.append(item)
    return JSONResponse(result)

@csrf_exempt
@permission_required('account.add_department')
def department_save(request):
    id = request.GET.get('id')
    parent_id = request.GET.get('parent_id')
    data = json.loads(request.body)

    try:
        with transaction.atomic():
            if id:
                department = Department.getById(id)
                department.name = data['name']
                department.notes = data['notes']
                department.save()
                BizLog.objects.addnew(request.user, BizLog.UPDATE, u"修改部门[%s],id=%d" % (data['name'], department.id))
            else:
                if parent_id:
                    parent = Department.getById(parent_id)
                    company_id = parent.company_id
                    parent_id = parent.id
                else:
                    parent = None
                    parent_id = None
                    company_id = None
                lft = Department.getLft(parent)

                Department.objects.filter(rgt__gt=lft).update(rgt=F('rgt') + 2)
                Department.objects.filter(lft__gt=lft).update(lft=F('lft') + 2)

                department = Department.objects.create(
                    name=data['name'],
                    notes=data['notes'],
                    parent_id=parent_id,
                    company_id=company_id,
                    lft=lft+1,
                    rgt=lft+2
                )

                if department.company_id == None:
                    department.company_id = department.id
                    department.save()

                BizLog.objects.addnew(request.user, BizLog.INSERT, u"添加部门[%s],id=%d" % (data['name'], department.id))


            if department.id == department.company_id and data['product_range']:
                department.product_range = int(data['product_range'])
                department.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('account.delete_department')
def department_delete(request):
    id = request.GET.get('id')

    try:
        with transaction.atomic():
            if Department.objects.filter(parent_id=id).count() > 0:
                raise CustomError(u'该部门存在子部门, 不允许删除')

            dep = Department.getById(id)
            lft = dep.lft
            rgt = dep.rgt

            total = rgt - lft + 1

            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除部门[%s],id=%d" % (dep.name, dep.id))

            dep.delete()
            Department.objects.filter(rgt__gt=lft).update(rgt=F('rgt')-total)
            Department.objects.filter(lft__gt=lft).update(lft=F('lft')-total)

    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
@token_required
def department_tree(request):
    def child_department_tree(parent_id,children):
        rows = Department.objects.filter(parent_id=parent_id)
        for row in rows:
            item = {
                'id': row.id,
                'value': row.id,
                'name': row.name,
                'notes': row.notes,
                'parent_id': row.parent_id,
                'children': []
            }
            child_department_tree(row.id,item['children'])
            children.append(item)

    result = []
    child_department_tree(None,result)
    return JSONResponse(result)

@csrf_exempt
@token_required
def select_department(request):
    result = []
    rows = Department.objects.filter()
    for row in rows:
        item = {
            'id': row.id,
            'name': row.name
        }
        result.append(item)
    return JSONResponse(result)

@token_required
def home_count(request):
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    warehouses_ids = Warehouse.getManagerWarehouses(request.user)
    sale_plan_count = SalePlan.objects.filter(Q(create_user_id__in=user_ids) | Q(department_id__in=department_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    sale_order_count = SaleOrder.objects.filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    production_count = ProductionPlan.objects.filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    purchase_count = PurchasePlan.objects.filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    purchase_order_count = PurchaseOrder.objects.filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()

    material_godownentry_count = GodownEntry.objects.filter(product_type=GodownEntry.MATERIAL,warehouse_id__in=warehouses_ids).filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    material_deliver_count = Deliver.objects.filter(product_type=GodownEntry.MATERIAL,warehouse_id__in=warehouses_ids).filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    material_godownentry_return_count = GodownEntryReturn.objects.filter(type=GodownEntryReturn.MATERIAL, warehouse_id__in=warehouses_ids).filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    material_inventory_count = Inventory.objects.filter(product_type=Inventory.MATERIAL,warehouse_id__in=warehouses_ids).filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(check_status=settings.DEFAULT).count()

    consumable_godownentry_count = GodownEntry.objects.filter(product_type=GodownEntry.CONSUMABLE,warehouse_id__in=warehouses_ids).filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    consumable_deliver_count = Deliver.objects.filter(product_type=GodownEntry.CONSUMABLE,warehouse_id__in=warehouses_ids).filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    consumable_godownentry_return_count = GodownEntryReturn.objects.filter(type=GodownEntryReturn.CONSUMABLE, warehouse_id__in=warehouses_ids).filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    consumable_inventory_count = Inventory.objects.filter(product_type=Inventory.CONSUMABLE,warehouse_id__in=warehouses_ids).filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(check_status=settings.DEFAULT).count()

    goods_godownentry_count = GoodsGodownEntry.objects.filter(warehouse_id__in=warehouses_ids).filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    goods_deliver_count = GoodsDeliver.objects.filter(warehouse_id__in=warehouses_ids).filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(status=settings.DEFAULT).count()
    goods_inventory_count = Inventory.objects.filter(product_type=Inventory.GOODS,warehouse_id__in=warehouses_ids).filter(Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user)).filter(check_status=settings.DEFAULT).count()

    children = request.user.getSubDepartmentIds()
    children.append(request.user.department.id)
    rows = Notice.objects.filter(dendline__gte=timezone.now(), department__in=children)
    browsed_ids = NoticeBrowseRecord.objects.filter(browse_user_id=request.user).values_list('notice_id', flat=True)
    not_notices = rows.filter(~Q(id__in=browsed_ids))

    data = {
        'notice_unread': not_notices.count(),
        'sale_plan_count': sale_plan_count,
        'sale_order_count': sale_order_count,
        'production_count': production_count,
        'purchase_count': purchase_count,
        'purchase_order_count': purchase_order_count,

        'material_godownentry_count': material_godownentry_count,
        'material_deliver_count': material_deliver_count,
        'material_godownentry_return_count': material_godownentry_return_count,
        'material_inventory_count': material_inventory_count,

        'consumable_godownentry_count': consumable_godownentry_count,
        'consumable_deliver_count': consumable_deliver_count,
        'consumable_godownentry_return_count': consumable_godownentry_return_count,
        'consumable_inventory_count': consumable_inventory_count,

        'goods_godownentry_count': goods_godownentry_count,
        'goods_deliver_count': goods_deliver_count,
        'goods_inventory_count': goods_inventory_count,
    }
    return JSONResponse(data)
