# -*- coding: utf-8 -*-
# Copyright 2018 JDG <www.yunside.com>
# Create by Carmen <carmen.ling@yunside.com> at 2018/5/17

from odoo import models, fields, api
from odoo.exceptions import ValidationError
from odoo.osv import expression
import operator as py_operator
import logging
import json

_logger = logging.getLogger(__name__)

OPERATORS = {
    '<': py_operator.lt,
    '>': py_operator.gt,
    '<=': py_operator.le,
    '>=': py_operator.ge,
    '=': py_operator.eq,
    '!=': py_operator.ne
}

class AbstractBase(models.AbstractModel):
    """
    基础基类
    """

    _name = 'jdg.abstract.base'
    _inherit = 'jdg.abstract.core'
    _description = u"基础基类"
    _order = 'number'

    number = fields.Char(string=u'编号', required=True, index=True, copy=False, default='/',
                         help=u'编号规则：自动产生或每对象手工设置，基础数据一般为：01，01.01，业务单据一般为：PO20180101003')
    company_id = fields.Many2one('res.company', string=u'组织',
                                 index=True, default=lambda self: self.env.user.company_id)
    active = fields.Boolean(u'有效', default=True)
    note = fields.Text(u'备注')
    create_uid = fields.Many2one('res.users', string='创建人')
    write_uid = fields.Many2one('res.users', string='修改人')
    create_date = fields.Datetime('创建时间')
    write_date = fields.Datetime('修改时间')
    can_audit = fields.Boolean(string=u'是否可见审核/启用按钮', default=False, compute='get_can_audit')
    can_unaudit = fields.Boolean(string=u'是否可见反审核/停用按钮', default=False, compute='get_can_unaudit')

    @api.model
    def _search_abstract(self, operator, value, field):
        """
        searching on a computed field can also be enabled by setting the ``search``
        parameter. The value is a method name returning a
        """
        ids = []
        # Order the search on `id` to prevent the default order on the product name which slows
        # down the search because of the join on the translation table to get the translated names.
        for item in self.search([], order='id'):
            if OPERATORS[operator](item[field], value):
                ids.append(item.id)
        return [('id', 'in', ids)]

    @api.multi
    def get_can_audit(self):
        for record in self:
            try:
                can_audit = self.check_access_rights('audit')
                if can_audit:
                    record.can_audit = True
                else:
                    record.can_audit = False
            except Exception as e:
                record.can_audit = False

    @api.multi
    def get_can_unaudit(self):
        for record in self:
            try:
                can_unaudit = self.check_access_rights('unaudit')
                if can_unaudit:
                    record.can_unaudit = True
                else:
                    record.can_unaudit = False
            except Exception as e:
                record.can_unaudit = False

    @api.multi
    @api.depends('number')
    def name_get(self):
        """
        名称显示格式：[XXX]YYY
        """
        result = []
        for record in self:
            name = '[%s]' % record.number
            result.append((record.id, name))
        return result

    def get_value_display(self, result, key, value):
        """
        传入字段名以及字段值
        将many2one,one2many,selection,many2many字段转化为用户可读的形式
        :param result:
        :param key:
        :param value:
        :return:
        """
        value_display = value
        if self._fields[key].type == 'selection':
            value_display = dict(self._fields[key].selection).get(value)
        elif self._fields[key].type == 'many2one':
            if value and not isinstance(value, int) and not (isinstance(value, unicode) and value.isdigit()):
                value = value.id
            rs = self.env[self._fields[key].comodel_name].browse(value)
            if hasattr(rs, 'name'):
                value_display = str(rs.name)
            elif hasattr(rs, 'number'):
                value_display = str(rs.number)
            else:
                value_display = str(rs.id)
            if not value_display:
                value_display = ''
        elif self._fields[key].type == 'boolean':
            value_display = '否' if not value else '是'
        elif self._fields[key].type == 'one2many':
            lines_str = ''
            index = 1
            for line in value:
                lines_str += "\n - %s - " % index
                index += 1
                for f in self.env[self._fields[key].comodel_name]._fields:
                    field_info = self.env[self._fields[key].comodel_name]._fields[f]
                    if field_info.type == 'selection':
                        lines_str += "\n" + field_info.string + "：" + dict(field_info.selection).get(line[f])
                    elif field_info.type == 'many2one':
                        if hasattr(line[f], 'name'):
                            info = line[f].name
                        elif hasattr(line[f], 'number'):
                            info = line[f].number
                        else:
                            info = line[f].id
                        lines_str += "\n" + field_info.string + "：" + str(info) if info else ''
                    elif field_info.type == 'boolean':
                        boolean_str = '是' if line[f] else '否'
                        lines_str += "\n" + field_info.string + "：" + boolean_str
                    elif field_info.type == 'many2many':
                        value_str = "\n" + field_info.string + "：%s"
                        value_lines = []
                        for l in line[f]:
                            if hasattr(l, 'name'):
                                value_lines.append(str(l.name))
                            elif hasattr(l, 'number'):
                                value_lines.append(str(l.number))
                            else:
                                value_lines.append(str(l.id))
                        lines_str += value_str % value_lines
                    else:
                        lines_str += "\n" + field_info.string + "：" + str(line[f])
            value_display = lines_str
        elif self._fields[key].type == 'many2many':
            lines_str = '%s'
            value_lines = []
            for line in value:
                if hasattr(line, 'name'):
                    value_lines.append(str(line.name))
                elif hasattr(line, 'number'):
                    value_lines.append(str(line.number))
                else:
                    value_lines.append(str(line.id))
            value_display = lines_str % value_lines
        return str(value_display)

    @api.model
    def create(self, values):
        """
        监控变化字段
        :param values:
        :return:
        """
        result = super(AbstractBase, self).create(values)
        self.env['jd.system.log.biz'].jdg_sudo().do_logging(result.company_id.id or None, self.env.user.id, 'create', self._name, result.id, result.number)
        return result

    @api.multi
    def write(self, values):
        """
        监控变化字段
        :param values:
        :return:
        """
        _logger.info(values)

        log_fields = self.env['jd.system.log.biz'].jdg_sudo().get_write_config(self._name, values.keys()) if values else []
        
        write_fields = {}
        for l in log_fields:
            value_before = self.get_value_display(self, l, self[l])
            write_fields[l] = {
                'field': l,
                'field_cn': self._fields[l].string,
                'value_before': value_before,
                'value_after' : None
            }
        result = super(AbstractBase, self).write(values)
        for l in log_fields:
            value_after = self.get_value_display(self, l, self[l])
            if write_fields[l]['value_before'] != value_after:
                write_fields[l].update({
                    'value_after': value_after
                })
            else:
                write_fields.pop(l)
        if write_fields:
            write_fields = json.dumps(write_fields.values())
            self.env['jd.system.log.biz'].jdg_sudo().do_logging(self.company_id.id or None, self.env.user.id, 'write', self._name, self.id, self.number, write_fields)

        return result
    
    @api.multi
    def unlink(self):
        for record in self:
            self.env['jd.system.log.biz'].jdg_sudo().do_logging(record.company_id.id or None, self.env.user.id, 'unlink', self._name, record.id, record.number)
        return super(AbstractBase, self).unlink()

    # @api.model
    # def name_search(self, name, args=None, offset=0, operator='ilike', limit=100, order=None, count=False,
    #                 name_get_uid=None):
    #     """
    #     名称模糊搜索
    #     :return:
    #     """
    #     args = args or []
    #     domain = []
    #     if name:
    #         domain = ['|', ('number', '=ilike', '%' + name + '%'), ('name', operator, name)]
    #         if operator in expression.NEGATIVE_TERM_OPERATORS:
    #             domain = ['&', '!'] + domain[1:]
    #     records = self.search(domain + args, int(offset), limit, order, count)
    #     return records.name_get()

    @api.model
    def name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
        """
        名称模糊搜索:去掉name模糊条件；
        Updated By YGJ @2018/5/23
        :return:
        """
        args = args or []
        domain = []
        if name:
            domain = [('number', '=ilike', '%' + name + '%')]
            if operator in expression.NEGATIVE_TERM_OPERATORS:
                domain = ['&', '!'] + domain[1:]
        records = self.search(domain + args, limit=limit)
        return records.name_get()

    # _sql_constraints = [
    #     ('number_uniq', 'unique (number,company_id)', u'编号重复！')
    # ]
