# -*- coding: utf-8 -*-
# 项目: jdg-core-base
# Copyright 2018 JDG <www.yunside.com>
# Created by HJH <jiahao.huang@yunside.com> at 2022/05/18

from odoo import models, fields, api
from odoo.exceptions import ValidationError
import json
import logging

_logger = logging.getLogger(__name__)

ACTION = [
    ('create', u'创建'),
    ('write', u'修改'),
    ('audit', u'审核'),
    ('unaudit', u'反审核'),
    ('cancel', u'作废'),
    ('unlink', u'删除')
]


class JdBizLog(models.Model):
    _name = 'jd.biz.log'
    _description = u'单据日志'

    company_id = fields.Many2one('res.company', string=u'单据组织')
    user_id = fields.Many2one('res.users', string=u'操作用户')
    user_login = fields.Char(string=u'账号', compute='_get_user_login')
    time_op = fields.Datetime(string=u'操作时间')
    action = fields.Selection(ACTION, string=u'操作')
    source = fields.Reference(string=u'单据', selection='_reference_models')
    source_number = fields.Char(string=u'单据编码')
    model_id = fields.Many2one('ir.model', string=u'单据类型')
    line_ids = fields.One2many('jd.biz.log.line', 'parent_id', string=u'日志明细')

    @api.multi
    @api.depends('user_id')
    def _get_user_login(self):
        for item in self:
            if item.user_id and item.user_id.login:
                item.user_login = item.user_id.login

    @api.model
    def _reference_models(self):
        cr = self.env.cr
        sql = """
          SELECT
            model,
            name
          FROM ir_model;
        """
        cr.execute(sql)
        recs = cr.dictfetchall()
        return [(rec['model'], rec['name']) for rec in recs]
    
    @api.model
    def get_write_config(self, name, write_fields):
        if not write_fields or not name:
            return []
        cr = self.env.cr
        sql = """
          SELECT
            id
          FROM ir_model
          WHERE model = %s;
        """
        cr.execute(sql, (name, ))
        rec = cr.dictfetchone()
        if rec and rec.get('id'):
            model_id = rec['id']
        else:
            return []

        sql = """
          SELECT 
            array_agg(imf.name)             AS log_fields
          FROM (
            SELECT
              DISTINCT ON (imf.id)
              imf.name
            FROM jd_log_config lc
              INNER JOIN jd_log_config_line lcl ON lcl.parent_id = lc.id
                                               AND lcl.model_id = %(model_id)s
                                               AND lcl.mon_write = TRUE
              INNER JOIN rel_log_write_model_fields rel ON rel.config_line_id = lcl.id
                                                       AND lcl.mon_write = TRUE
              INNER JOIN ir_model_fields imf ON imf.id = rel.field_id
                                            AND imf.model_id = %(model_id)s
            WHERE lc.state = 'enable'
              AND lcl.mon_write = TRUE
              AND lcl.model_id = %(model_id)s
              AND imf.name = ANY(%(write_fields)s)
          ) imf
        """
        cr.execute(sql, {
            'model_id': model_id,
            'write_fields': write_fields
        })
        rec = cr.dictfetchone()
        if rec and rec.get('log_fields'):
            return rec['log_fields']
        else:
            return []
    
    @api.model
    def do_logging(self, company_id, user_id, action, name, id, number, write_fields=None):
        cr = self.env.cr
        sql = """
          SELECT
            max(CASE WHEN lcl.mon_create = TRUE THEN 1 ELSE 0 END)      AS mon_create,
            max(CASE WHEN lcl.mon_write = TRUE THEN 1 ELSE 0 END)       AS mon_write,
            max(CASE WHEN lcl.mon_audit = TRUE THEN 1 ELSE 0 END)       AS mon_audit,
            max(CASE WHEN lcl.mon_unaudit = TRUE THEN 1 ELSE 0 END)     AS mon_unaudit,
            max(CASE WHEN lcl.mon_cancel = TRUE THEN 1 ELSE 0 END)      AS mon_cancel,
            max(CASE WHEN lcl.mon_unlink = TRUE THEN 1 ELSE 0 END)      AS mon_unlink,
            im.id                                                       AS model_id,
            lc.id                                                       AS config_id
          FROM jd_log_config lc
            INNER JOIN jd_log_config_line lcl ON lcl.parent_id = lc.id
            INNER JOIN ir_model im ON im.id = lcl.model_id
          WHERE lc.state = 'enable'
            AND im.model = %s
          GROUP BY lc.id, im.id;
        """
        cr.execute(sql, (name,))
        rec = cr.dictfetchone()
        if rec and rec.get('mon_%s' % action):
            # has action monitor
            model_id = rec.get('model_id', 0)
            config_id = rec.get('config_id', 0)
            sql = """
              INSERT INTO jd_biz_log (
                create_uid, create_date, write_uid, write_date,
                company_id, user_id, time_op, action, source, 
                source_number, model_id
              )
              VALUES (
                1, CURRENT_TIMESTAMP AT TIME ZONE 'UTC', 1, CURRENT_TIMESTAMP AT TIME ZONE 'UTC',
                %(company_id)s, %(user_id)s, CURRENT_TIMESTAMP AT TIME ZONE 'UTC', %(action)s, %(source)s, 
                %(source_number)s, %(model_id)s
              )
              RETURNING id;
            """
            cr.execute(sql, {
                'company_id': company_id,
                'user_id': user_id,
                'action': action,
                'source': '%s,%s'% (name, id),
                'source_number': number,
                'model_id': model_id
            })
            rec = cr.dictfetchone()
            log_id = rec['id']
            if action == 'write' and write_fields:
                cr.callproc('JD_CREATE_BIZ_LOG_LINE', [log_id, write_fields])


class JdBizLogLine(models.Model):
    _name = 'jd.biz.log.line'
    _description = u'单据日志明细'

    parent_id = fields.Many2one('jd.biz.log', string=u'单据日志')
    field = fields.Char(string=u'字段名')
    field_cn = fields.Char(string=u'字段中文')
    value_before = fields.Text(string=u'字段原值')
    value_after = fields.Text(string=u'修改后值')
