package cn.ibizlab.businesscentral.core.extensions.service;

import cn.ibizlab.businesscentral.core.odoo_base.domain.Res_partner;
import cn.ibizlab.businesscentral.core.odoo_base.service.IRes_partnerService;
import cn.ibizlab.businesscentral.core.odoo_ir.domain.Ir_model_fields;
import cn.ibizlab.businesscentral.core.odoo_ir.filter.Ir_model_fieldsSearchContext;
import cn.ibizlab.businesscentral.core.odoo_ir.service.IIr_model_fieldsService;
import cn.ibizlab.businesscentral.core.odoo_mail.domain.Mail_message;
import cn.ibizlab.businesscentral.core.odoo_mail.domain.Mail_message_subtype;
import cn.ibizlab.businesscentral.core.odoo_mail.service.IMail_messageService;
import cn.ibizlab.businesscentral.core.odoo_mail.service.IMail_tracking_valueService;
import cn.ibizlab.businesscentral.core.odoo_mail.service.impl.Mail_tracking_valueServiceImpl;
import cn.ibizlab.businesscentral.core.util.helper.EBSServiceImpl;
import cn.ibizlab.businesscentral.util.domain.EntityMP;
import cn.ibizlab.businesscentral.util.helper.CaseFormatMethod;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import cn.ibizlab.businesscentral.core.odoo_mail.domain.Mail_tracking_value;
import org.apache.commons.lang3.StringUtils;
import org.javers.core.JaversBuilder;
import org.javers.core.diff.Change;
import org.javers.core.diff.Diff;
import org.javers.core.diff.changetype.ValueChange;
import org.javers.core.metamodel.clazz.EntityDefinitionBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.context.annotation.Primary;

import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 实体[邮件跟踪值] 自定义服务对象
 */
@Slf4j
@Primary
@Service("Mail_tracking_valueExService")
public class Mail_tracking_valueExService extends Mail_tracking_valueServiceImpl {

    @Autowired
    IIr_model_fieldsService ir_model_fieldsService;

    @Autowired
    IMail_messageService mail_messageService;

    @Autowired
    IRes_partnerService res_partnerService;

    @Autowired
    IMail_tracking_valueService mail_tracking_valueService;

    @Override
    protected Class currentModelClass() {
        return com.baomidou.mybatisplus.core.toolkit.ReflectionKit.getSuperClassGenericType(this.getClass().getSuperclass(), 1);
    }

    @Transactional
    public <T extends EntityMP> List<Mail_tracking_value> message_track(EBSServiceImpl service, T _old, T _new) {
        List<Mail_tracking_value> tracking_values = new ArrayList<>();
        List<Ir_model_fields> fields = this.getIr_fields(service);
        if (fields.size() == 0)
            return tracking_values;

        List<String> strCodeFields = fields.stream().map(u -> CaseFormatMethod.exec(u.getName(), "l_u2lC")).collect(Collectors.toList());
        strCodeFields.add("id");
        JaversBuilder javersBuilder = JaversBuilder.javers();
        EntityDefinitionBuilder entityDefinitionBuilder = EntityDefinitionBuilder.entityDefinition(_old.getClass());
        entityDefinitionBuilder.withIdPropertyName("id");
        entityDefinitionBuilder.withIncludedProperties(strCodeFields);
        javersBuilder.registerType(entityDefinitionBuilder.build());
        Diff diff = javersBuilder.build().compare(_old, _new);

        if (!diff.hasChanges())
            return tracking_values;

        Mail_message_subtype message_subtype = service.getMessageSubType(_new, diff);

        Mail_message message = new Mail_message();
        message.setMessageId("message-notify");
        message.setDate(new Timestamp(System.currentTimeMillis()));
        message.setModel(service.getIrModel());
        message.setResId(((Long) _old.get("id")).intValue());
        message.setBody("");

        //
        message.setSubtypeId(message_subtype.getId());
        if (message_subtype.getId() != 2) {
            Mail_message parentMessage = mail_messageService.getOne(new QueryWrapper<Mail_message>()
                    .eq("res_id", message.getId())
                    .ne("message_type", "user_notification")
                    .orderByAsc("id").last("limit 1"));
            if (parentMessage != null) {
                message.setParentId(parentMessage.getId());
            }
            message.setRecordName(_new.get("displayName") != null ? _new.get("displayName").toString() : "");
            message.setMessageType(String.format("%s-%s", message.getResId(), message.getModel()));
        } else {
            message.setMessageType("notification");
        }
        Res_partner res_partner = res_partnerService.get(3l);
        message.setAuthorId(res_partner.getId());
        message.setEmailFrom(String.format("\"%s\" <%s>", res_partner.getName(), res_partner.getEmail()));
        message.setReplyTo("");
        message.setAddSign(true);
        message.setWebsitePublished(true);
        mail_messageService.create(message);

        for (Change change : diff.getChanges()) {
            if (change instanceof ValueChange) {
                ValueChange vchange = (ValueChange) change;
                String str_ir_model_fields = CaseFormatMethod.exec(vchange.getPropertyName(), "lC2l_u");
                Ir_model_fields ir_model_fields = fields.stream().filter(s -> {
                    return s.getName().equals(str_ir_model_fields);
                }).findAny().get();
                Mail_tracking_value tracking_value = new Mail_tracking_value();
                tracking_value.setMailMessageId(message.getId());
                tracking_value.setField(ir_model_fields.getName());
                tracking_value.setFieldDesc(ir_model_fields.getFieldDescription());
                tracking_value.setFieldType(ir_model_fields.getTtype());
                tracking_value.setTrackingSequence(ir_model_fields.getTracking());
                setTrackingValue(tracking_value, ir_model_fields, vchange);
                mail_tracking_valueService.create(tracking_value);
                tracking_values.add(tracking_value);

            }
        }

        return tracking_values;
    }

    private void setTrackingValue(Mail_tracking_value mail_tracking_value, Ir_model_fields ir_model_fields, ValueChange vchange) {
        if (StringUtils.compare(ir_model_fields.getTtype(), "date") == 0 || StringUtils.compare(ir_model_fields.getTtype(), "datetime") == 0) {
            mail_tracking_value.set("oldValueDatetime", vchange.getLeft());
            mail_tracking_value.set("newValueDatetime", vchange.getRight());
        } else if (StringUtils.compare(ir_model_fields.getTtype(), "integer") == 0 || StringUtils.compare(ir_model_fields.getTtype(), "many2one") == 0) {
            mail_tracking_value.set("oldValueInteger", vchange.getLeft());
            mail_tracking_value.set("newValueInteger", vchange.getRight());
        } else if (StringUtils.compare(ir_model_fields.getTtype(), "float") == 0) {
            mail_tracking_value.set("oldValueFloat", vchange.getLeft());
            mail_tracking_value.set("newValueFloat", vchange.getRight());
        } else if (StringUtils.compare(ir_model_fields.getTtype(), "monetary") == 0) {
            mail_tracking_value.set("oldValueMonetary", vchange.getLeft());
            mail_tracking_value.set("newValueMonetary", vchange.getRight());
        } else if (StringUtils.compare(ir_model_fields.getTtype(), "selection") == 0) {
            mail_tracking_value.set("oldValueChar", vchange.getLeft());
            mail_tracking_value.set("newValueChar", vchange.getRight());
        } else if (StringUtils.compare(ir_model_fields.getTtype(), "text") == 0) {
            mail_tracking_value.set("oldValueText", vchange.getLeft());
            mail_tracking_value.set("newValueText", vchange.getRight());
        } else {
            mail_tracking_value.set("oldValueChar", vchange.getLeft());
            mail_tracking_value.set("newValueChar", vchange.getRight());
        }
    }

    private Map<String, List<Ir_model_fields>> ir_model_fieldsMap = new HashMap<>();

    private <T extends EntityMP> List<Ir_model_fields> getIr_fields(EBSServiceImpl service) {
        if (ir_model_fieldsMap.containsKey(service.getIrModel()))
            return ir_model_fieldsMap.get(service.getIrModel());
        Ir_model_fieldsSearchContext ctx = new Ir_model_fieldsSearchContext();
        ctx.setN_model_eq(service.getIrModel());
        List<Ir_model_fields> fields = ir_model_fieldsService.searchTrackingFields(ctx).getContent();
        ir_model_fieldsMap.put(service.getIrModel(), fields);
        return fields;
    }


}

