import time
from copy import deepcopy

from django.db import transaction

from common.utils.str_utils import make_uuid, name_maker
from common.accounts.models import (Enterprise, Users, Accounts,
                                    UserEnterprise, UserRoles, UserTags, Roles)
from common.accounts.services import user_service
from common.third_party_api.amap.openapi import AmapApi
from common.utils.exceptions import ValidationError
from common.accounts.repositories import user_repo
from console.customer.repositories import custom_repo, custom_sql_repo
from console.customer.models import (Customer, CustomerAdmin, Contact,
                                     ContactTags)
from console.electricityuser.models import ElectricityUser
from console.powerstation.models import PowerStation


class CustomerService(object):
    @transaction.atomic()
    def update_customer(self, customer, request_data):
        province = request_data.get('province')
        city = request_data.get('city')
        county = request_data.get('county')
        address = request_data.get('address')
        addr = (([province, ''][province is None]) +
                ([city, ''][city is None]) + ([county, ''][county is None]) +
                ([address, ''][address is None]))
        geocodes = AmapApi().geo(address=str(addr))['geocodes']
        if not len(geocodes):
            raise ValidationError('无效地址')

        enterprise_data = {
            'logo': request_data.get('logo'),
            'file': request_data.get('file'),
            'adcode': geocodes[0]['adcode'],
            'address': request_data.get('address'),
            'industry': request_data.get('industry'),
            'scale': request_data.get('scale'),
            'asset': request_data.get('asset'),
            'longitude': request_data.get('longitude'),
            'latitude': request_data.get('latitude'),
            'covered_area': request_data.get('covered_area')
        }
        customer.enterprise.__dict__.update(**enterprise_data)
        customer.enterprise.save()
        tp = request_data.get('type')
        if not isinstance(tp, list):
            raise ValidationError("客户类型参数验证错误")
        tp = ','.join([str(i) for i in tp])
        customer_data = {
            'name': request_data.get('name'),
            'level': request_data.get('level'),
            'type': tp,
            'code': request_data.get('code'),
            'enterprise': customer.enterprise
        }
        customer.__dict__.update(**customer_data)
        if customer.last_service_staff_id == 0:
            customer.last_service_staff_id = None
        if customer.service_staff_id == 0:
            customer.service_staff_id = None
        customer.save()
        return customer

    @transaction.atomic()
    def bind_customer_admin(self, customer_id, user_id):
        CustomerAdmin.objects.create(customer_id=customer_id, user_id=user_id)

    def get_customer(self, id):
        return Customer.objects.filter(deleted=False, id=id).first()

    def get_customer_enterprise(self, customer_id):
        customer = Customer.objects.filter(id=customer_id).first()
        if not customer:
            raise ValidationError("该客户不存在")
        if customer.enterprise:
            return customer.enterprise
        else:
            return None

    def customers_info(self, enterprise_ids, **kwargs):
        return custom_sql_repo.customers_info(enterprise_ids, **kwargs)

    def get_customers(self, enterprise_ids, **kwargs):
        return custom_sql_repo.get_customers(enterprise_ids, **kwargs)

    def customers_report(self, enterprise_ids, year_month, customer_ids):
        return custom_sql_repo.customers_report(enterprise_ids, year_month,
                                                customer_ids)

    def customers_report_info(self, electrical_user_id, year_month, old_month):
        return custom_sql_repo.customers_report_info(electrical_user_id,
                                                     year_month, old_month)

    def customers_report_list_info(self, electrical_user_id, year_month, old_month):
        return custom_sql_repo.customers_report_list_info(electrical_user_id,
                                                     year_month, old_month)

    def create_customer_enterprise(self, data):
        if not data:
            return
        enterprise_id = data.pop("id", None)
        if enterprise_id:
            enterprise = user_repo.enterprise_id(id=enterprise_id)
            if not enterprise:
                raise ValidationError("该客户公司不存在")
            return enterprise
        data["enterprise_id"] = make_uuid()
        return Enterprise.objects.create(**data)

    @transaction.atomic()
    def create_customer_contact(self, data):
        contact_tag_list = []
        tags = data.pop("tags", [])
        contact = Contact.objects.create(**data)
        for i in tags:
            contact_tag_list.append(
                ContactTags(tag_id=i, contact_id=contact.id))
        ContactTags.objects.bulk_create(contact_tag_list)
        return contact

    @transaction.atomic()
    def update_customer_contact(self, data):
        contact_tag_list = []
        tags = data.pop("tags", [])
        id = data["id"]
        contact = Contact.objects.filter(id=id)
        contact.update(**data)
        ContactTags.objects.filter(contact_id=id).delete()
        for i in tags:
            contact_tag_list.append(ContactTags(tag_id=i, contact_id=id))
        ContactTags.objects.bulk_create(contact_tag_list)
        return contact.first()

    @transaction.atomic()
    def delete_customer_contact(self, id):
        ContactTags.objects.filter(contact_id=id).delete()
        Contact.objects.filter(id=id).delete()

    def create_customer_contacts(self, data, customer_id):
        if not data:
            return
        contact_tag_list = []
        for row in data:
            tags = row.pop("tags", [])
            row["customer_id"] = customer_id
            contact = Contact.objects.create(**row)
            for i in tags:
                contact_tag_list.append(
                    ContactTags(tag_id=i, contact_id=contact.id))
        if contact_tag_list:
            ContactTags.objects.bulk_create(contact_tag_list)

    def create_customer_admin(self, data, customer_id, enterprise_id):
        if not data:
            return
        customer_admin_list = []
        user_enterprise_list = []
        user_ids = []
        user_tags = []
        for row in data:
            password = row["password"]
            username = row["username"]
            tags = row.pop("tags", [])
            account = Accounts.objects.create(username=username,
                                              is_active=True,
                                              certification_status=True,
                                              account_type="customer")
            account.set_password(password)
            account.save()
            user = Users.objects.create(nickname=row["nickname"],
                                        email=row["email"],
                                        wechat=row["wechat"],
                                        phone=row["phone"],
                                        account=account)
            user_ids.append(user.id)
        #     for tag in tags:
        #         user_tags.append(ContactTags(tag_id=tag, contact_id=id))
        #     user_ids.append(user.id)
        # if user_tags:
        #     ContactTags.objects.bulk_create(user_tags)
        enterprise = Enterprise.objects.filter(id=enterprise_id).first()
        for user_id in user_ids:
            customer_admin_list.append(
                CustomerAdmin(customer_id=customer_id, user_id=user_id))
            user_enterprise_list.append(
                UserEnterprise(user_id=user_id, enterprise_id=enterprise.enterprise_id))
        CustomerAdmin.objects.bulk_create(customer_admin_list)
        UserEnterprise.objects.bulk_create(user_enterprise_list)

    def create_electricity_user(self, data, customer_id):
        if not data:
            return
        electricity_user_list = []
        for row in data:
            row["customer_id"] = customer_id
            electricity_user_list.append(ElectricityUser(**row))
        ElectricityUser.objects.bulk_create(electricity_user_list)

    @transaction.atomic()
    def create_customer_info(self, data):
        enterprise_dt = data.pop("enterprise", [])
        contacts_dt = data.pop("contacts", [])
        electricity_user_dt = data.pop("electricity_user", [])
        data.pop("customer_id", None)
        customer_admin_dt = data.pop("customer_admin", [])
        enterprise = self.create_customer_enterprise(enterprise_dt)
        data["enterprise_id"] = enterprise.id
        data["type"] = ','.join([str(i) for i in data["type"]])
        data["code"] = name_maker("cst", 12)
        customer = Customer.objects.create(**data)
        customer_id = customer.id
        self.create_customer_contacts(contacts_dt, customer_id)
        self.create_customer_admin(customer_admin_dt, customer_id,
                                   enterprise.enterprise_id)
        self.create_electricity_user(electricity_user_dt, customer_id)
        return customer

    @transaction.atomic()
    def update_customer_info(self, data):
        enterprise = data.pop("enterprise", None)
        customer_admin = data.pop("customer_admin", None)
        contacts = data.pop("contacts", None)
        customer_id = data.get("id")
        enterprise_id = data.get("enterprise_id")
        self._update_customer(data)
        self._update_enterprise(enterprise)
        self._update_customer_admin(customer_admin, customer_id, enterprise_id)
        self._update_contact(contacts, customer_id)

    def _update_customer(self, data):
        if data:
            id = data.pop("id", None)
            type = data.pop("type", [])
            if id:
                if type:
                    if isinstance(type, list):
                        data["type"] = ",".join([str(i) for i in type])
                    else:
                        data["type"] = type
                Customer.objects.filter(id=id).update(**data)

    def _update_enterprise(self, data):
        if data:
            id = data.pop("id", None)
            if id:
                Enterprise.objects.filter(id=id).update(**data)

    def _update_customer_admin(self, data, customer_id, enterprise_id):
        if data:
            customer_admin_dt = []
            for dt in data:
                id = dt.pop("id", None)
                if id:
                    password = dt.pop("password", None)
                    username = dt.pop("username", None)
                    tags = dt.pop("tags", [])
                    dt.pop("customer_id", None)
                    users = Users.objects.filter(id=id)
                    Users.objects.filter(id=id).update(**dt)
                    user = users.first()
                    if user.account_id:
                        account = Accounts.objects.filter(id=user.account_id).first()
                        account.username = username
                        if password:
                            account.set_password(password)
                        account.save()
                    user_tags = []
                    UserTags.objects.filter(user_id=id).delete()
                    for tag in tags:
                        user_tags.append(UserTags(tag_id=tag, user_id=id))
                    UserTags.objects.bulk_create(user_tags)
                else:
                    customer_admin_dt.append(dt)
                self.create_customer_admin(customer_admin_dt, customer_id, enterprise_id)

    def _update_contact(self, data, customer_id):
        if data:
            contact_dt = []
            for dt in data:
                id = dt.pop("id", None)
                dt.pop("customer_id", None)
                tags = dt.pop("tags", [])
                if id:
                    contact_tags = []
                    Contact.objects.filter(id=id).update(**dt)
                    ContactTags.objects.filter(contact_id=id).delete()
                    for tag in tags:
                        contact_tags.append(ContactTags(tag_id=tag, contact_id=id))
                    ContactTags.objects.bulk_create(contact_tags)
                else:
                    contact_dt.append(dt)
            self.create_customer_contacts(contact_dt, customer_id)

    @transaction.atomic()
    def delete_customer(self, pk_list):
        Customer.objects.filter(id__in=pk_list).update(
            deleted=True,
            deleted_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
        ElectricityUser.objects.filter(customer_id__in=pk_list).update(
            deleted=True,
            deleted_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
        PowerStation.objects.filter(customer_id__in=pk_list).update(
            deleted=True,
            deleted_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

    def get_contacts(self, **kwargs):
        return custom_repo.get_contacts(**kwargs)

    def get_customer_map(self, **kwargs):
        return custom_repo.get_customer_map(**kwargs)

    def get_customer_electric_map(self, **kwargs):
        return custom_repo.get_customer_electric_map(**kwargs)

    def get_ele_map(self, **kwargs):

        return custom_repo.get_ele_map(**kwargs)

    def get_map(self, enterprise_ids, **kwargs):
        kw = kwargs.pop("kw", "customer")
        mp = {
            "customer": self.get_map_customer,
            "ele_user": self.get_map_ele_user,
            "ele_info": self.get_map_ele_info,
            "outline": self.get_map_outline,
        }
        if isinstance(kw, list):
            kw = kw[0]
        if kw not in mp.keys():
            return []
        return mp[kw](enterprise_ids, **kwargs)

    def get_map_customer(self, enterprise_ids, **kwargs):
        return custom_repo.get_map_customer(enterprise_ids, **kwargs)

    def get_map_ele_user(self, enterprise_ids, **kwargs):
        return custom_repo.get_map_ele_user(enterprise_ids, **kwargs)

    def get_map_ele_info(self, enterprise_ids, **kwargs):
        return custom_repo.get_map_ele_info(enterprise_ids, **kwargs)

    def get_map_outline(self, enterprise_ids, **kwargs):
        return custom_repo.get_map_outline(enterprise_ids, **kwargs)


class CustomerAdminService(object):
    @transaction.atomic()
    def delete_customer_admin(self, pk, enterprise_ids):
        for admin_id in pk:
            CustomerAdmin.objects.filter(deleted=False,
                                         user_id=admin_id).update(
                                             deleted=True,
                                             deleted_time=time.strftime(
                                                 "%Y-%m-%d %H:%M:%S",
                                                 time.localtime()))
            user_service.delete_user(admin_id, enterprise_ids)

    @transaction.atomic()
    def delete_customer_admin_by_id(self, id, customer_id):
        CustomerAdmin.objects.filter(user_id=id).delete()
        customer = Customer.objects.filter(id=customer_id).first()
        customer_ent = Enterprise.objects.filter(id=customer.enterprise_id).first()
        UserEnterprise.objects.filter(user_id=id, enterprise_id=customer_ent.enterprise_id).delete()
        if not UserEnterprise.objects.filter(user_id=id).first():
            UserRoles.objects.filter(user_id=id).delete()
            UserTags.objects.filter(user_id=id).delete()
            user = Users.objects.filter(id=id).first()
            account_id = user.account_id
            user.delete()
            Accounts.objects.filter(id=account_id).delete()
        else:
            role_ids = Roles.objects.filter(
                kind="enterprise", kind_id=customer_ent.enterprise_id).values_list("id", flat=True)
            if role_ids:
                UserRoles.objects.filter(user_id=id, role_id__in=role_ids).delete()

    def trans_data(self, data):
        res_data = []
        account = {}
        user = {}
        for item in data:
            if 'id' in item:
                user['id'] = item['id']
            if 'username' not in item:
                account['username'] = "default"
            else:
                account['username'] = item['username']
            if 'password' not in item:
                raise ValidationError('需要输入密码')
            else:
                account['password'] = item['password']
            account['certification_status'] = False
            account['account_type'] = "customer"
            if 'nickname' not in item:
                raise ValidationError('需要输入用户名')
            else:
                user['nickname'] = item['nickname']

            if 'phone' not in item:
                raise ValidationError('需要输入电话号码')
            else:
                user['phone'] = item['phone']
            user['wechat'] = ''
            user['email'] = ''
            user['account'] = account
            res_data.append(deepcopy(user))
        return res_data

    def get_customer_admin_id(self, data):
        if isinstance(data, list):
            pks = []
            for dic in data:
                if 'id' not in dic:
                    raise ValidationError("请输入id")
                pk = dic['id']
                pks.append(pk)
            return pks
        else:
            if 'id' not in data:
                raise ValidationError("请输入id")
            pk = data['id']
            return pk


customer_service = CustomerService()
custom_admin_service = CustomerAdminService()
