import json
import os
import cv2
import time
import logging
import traceback
import numpy as np
from datetime import datetime, timedelta
from collections import OrderedDict
from . import app
from settings import conf
from apps.doc.models import (
    AFCOCRResult,
    AFCSEOCRResult,
    HILOCRResult,
    HILSEOCRResult,
    AFCComparisonInfo,
    AFCSEComparisonInfo,
    AFCSECMSInfo,
    HILComparisonInfo,
    HILSEComparisonInfo,
    HILSECMSInfo,
    Configs,
    HILCompareReport,
    AFCCompareReport,
    AFCSECompareResult,
    AFCCACompareResult,
    HILSECompareResult,
    HILCACompareResult,
    HILAutoSettlement,
    AFCAutoSettlement,
)
from apps.doc import consts
from apps.doc.ocr.gcap import gcap
from apps.doc.ocr.cms import cms
from apps.doc.exceptions import GCAPException
from apps.doc.named_enum import RequestTeam, RequestTrigger, ProcessName, ErrorType
from common.tools.comparison import cp
from common.tools.des import decode_des

compare_log = logging.getLogger('compare')
log_base = '[Compare]'
# e_log_base = '[e-contract]'
empty_str = ''
empty_error_type = 1000
des_key = conf.CMS_DES_KEY


def rotate_bound(image, angle):
    # grab the dimensions of the image and then determine the
    # center
    (h, w) = image.shape[:2]
    (cX, cY) = (w // 2, h // 2)

    # grab the rotation matrix (applying the negative of the
    # angle to rotate clockwise), then grab the sine and cosine
    # (i.e., the rotation components of the matrix)
    M = cv2.getRotationMatrix2D((cX, cY), angle, 1.0)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])

    # compute the new bounding dimensions of the image
    nW = int((h * sin) + (w * cos))
    nH = int((h * cos) + (w * sin))

    # adjust the rotation matrix to take into account translation
    M[0, 2] += (nW / 2) - cX
    M[1, 2] += (nH / 2) - cY

    # perform the actual rotation and return the image
    return cv2.warpAffine(image, M, (nW, nH))


def build_coordinates(section_position_dict):
    if isinstance(section_position_dict, dict):
        h_min = section_position_dict.get('top', 0)
        w_min = section_position_dict.get('left', 0)
        h_max = h_min + section_position_dict.get('height', 0)
        w_max = w_min + section_position_dict.get('width', 0)
        if h_max > h_min and w_max > w_min:
            return True, (h_min, h_max, w_min, w_max)
        else:
            return False, ()
    return False, ()


def field_build_coordinates(field_position_info):
    field_position_dict = field_position_info.get(consts.FIELD_POSITION_KEY, {})
    field_quad_list = field_position_info.get(consts.FIELD_QUAD_KEY, [])
    if isinstance(field_quad_list, list) and len(field_quad_list) == 8:
        w_list = [field_quad_list[0], field_quad_list[2], field_quad_list[4], field_quad_list[6]]
        h_list = [field_quad_list[1], field_quad_list[3], field_quad_list[5], field_quad_list[7]]
        h_min = min(h_list)
        h_max = max(h_list)
        w_min = min(w_list)
        w_max = max(w_list)
        if h_max > h_min and w_max > w_min:
            return True, (h_min, h_max, w_min, w_max)
    if isinstance(field_position_dict, dict):
        h_min = field_position_dict.get('top', 0)
        w_min = field_position_dict.get('left', 0)
        h_max = h_min + field_position_dict.get('height', 0)
        w_max = w_min + field_position_dict.get('width', 0)
        if h_max > h_min and w_max > w_min:
            return True, (h_min, h_max, w_min, w_max)
        else:
            return False, ()
    return False, ()


def img_process(section_img_path, section_position, section_angle):
    image = cv2.imread(section_img_path)
    is_valid, coord_tuple = build_coordinates(section_position)
    if is_valid:
        image = image[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :]
    if isinstance(section_angle, int) or isinstance(section_angle, float):
        if section_angle != 0:
            return rotate_bound(image, section_angle)
    return image


def name_check(ocr_res_dict, second_ocr_field, second_compare_list, second_id_num, name):
    id_field = second_compare_list[1][1]
    name_field = second_compare_list[0][1]
    ocr_res_str = ocr_res_dict.get(second_ocr_field)
    if ocr_res_str is not None:
        ocr_res_list = json.loads(ocr_res_str)
        for ocr_res in ocr_res_list:
            ocr_second_id_num = ocr_res.get(id_field)
            if ocr_second_id_num == second_id_num:
                ocr_name = ocr_res.get(name_field)
                if ocr_name == name:
                    return True
    return False


def get_order_dict(src_dict, order_tuple):
    order_dict = OrderedDict({})
    for field in order_tuple:
        if field in src_dict:
            order_dict[field] = src_dict[field]
    return order_dict


def do_not_compare(info_dict, compare_list):
    for compare_tuple in compare_list:
        info_dict[compare_tuple[4]] = consts.RESULT_NA
        if compare_tuple[0] in info_dict:
            del info_dict[compare_tuple[0]]


def field_compare(info_dict, ocr_res_dict, ocr_field, compare_list, res_set,
                  has_expiry_date=False, sep_name=None, capital_ignore=False):
    is_find = False
    ocr_res_str = ocr_res_dict.get(ocr_field)
    if ocr_res_str is not None:
        ocr_res_list = json.loads(ocr_res_str)
        # length = len(ocr_res_list)

        # sep营业执照根据法人过滤
        if isinstance(sep_name, str):
            tmp_list = []
            for ocr_res in ocr_res_list:
                ocr_sep_name = ocr_res.get(consts.LEGAL_REP_NAME)
                if isinstance(ocr_sep_name, str) and ocr_sep_name == sep_name:
                    tmp_list.append(ocr_res)
        else:
            tmp_list = ocr_res_list

        length = len(tmp_list)

        # 过期期限特殊处理
        if has_expiry_date:
            expiry_dates = []
            key = compare_list[2][1]
            for ocr_res in tmp_list:
            # for ocr_res in ocr_res_list:
                if ocr_res.get(key):
                    expiry_dates.append(ocr_res.get(key))
        else:
            expiry_dates = []

        for res_idx in range(length-1, -1, -1):
        # for ocr_res in ocr_res_list:
            if is_find:
                break
            ocr_res = tmp_list[res_idx]
            for idx, compare_tuple in enumerate(compare_list):
                input_str = info_dict.get(compare_tuple[0])
                ocr_str = ocr_res.get(compare_tuple[1])
                compare_res, ocr_output = getattr(cp, compare_tuple[2])(
                    input_str, ocr_str, idx, **compare_tuple[3])
                # print('type: {0}, idx: {1}, field: {2}, input: {3}, ocr: {4}, res: {5}, out: {6}'.format(ocr_field, idx, compare_tuple[0], input_str, ocr_str, compare_res, ocr_output))
                if idx == 0 and compare_res in [consts.RESULT_N, consts.RESULT_NA] and length > 1:
                    break
                is_find = True

                # 过期期限特殊处理
                if idx == 2 and has_expiry_date and compare_res == consts.RESULT_NA:
                    for expiry_date in expiry_dates:
                        expiry_date_compare_res, expiry_date_ocr_output = getattr(cp, compare_tuple[2])(
                            input_str, expiry_date, idx, **compare_tuple[3]
                        )
                        if expiry_date_compare_res == consts.RESULT_Y:
                            compare_res = consts.RESULT_Y
                            ocr_output = expiry_date_ocr_output
                            ocr_str = expiry_date
                            break

                info_dict[compare_tuple[4]] = compare_res
                if input_str is not None:
                    if ocr_str is None or ocr_output is None:
                        del info_dict[compare_tuple[0]]
                    else:
                        info_dict[compare_tuple[0]] = ocr_output
                if capital_ignore and idx == 1:
                    pass
                elif capital_ignore and idx == 2 and input_str is None:
                    pass
                else:
                    res_set.add(compare_res)
    if not is_find:
        res_set.add(consts.RESULT_N)
        for compare_tuple in compare_list:
            info_dict[compare_tuple[4]] = consts.RESULT_NA
            if compare_tuple[0] in info_dict:
                del info_dict[compare_tuple[0]]


def usedcar_info_compare(info_dict, ocr_res_dict, ocr_field, compare_list, res_set):
    no_match_vino = []
    is_find = False
    key_right = False
    ocr_res_str = ocr_res_dict.get(ocr_field)
    if ocr_res_str is not None:
        ocr_res_list = json.loads(ocr_res_str)

        # 3、4页/副页去除
        # if ocr_field == consts.MVC_OCR_FIELD:
        tmp_list = []
        for res in ocr_res_list:
            if res.get(compare_list[0][1]) is not None:
                tmp_list.append(res)

        length = len(tmp_list)

        for res_idx in range(length-1, -1, -1):
            if is_find:
                break
            ocr_res = tmp_list[res_idx]
            for idx, compare_tuple in enumerate(compare_list):
                input_str = info_dict.get(compare_tuple[0])
                ocr_str = ocr_res.get(compare_tuple[1])
                compare_res, ocr_output = getattr(cp, compare_tuple[2])(
                    input_str, ocr_str, idx, **compare_tuple[3])
                # print('type: {0}, idx: {1}, field: {2}, input: {3}, ocr: {4}, res: {5}, out: {6}'.format(ocr_field, idx, compare_tuple[0], input_str, ocr_str, compare_res, ocr_output))
                if idx == 0 and compare_res in [consts.RESULT_N, consts.RESULT_NA]:
                    if ocr_str is not None:
                        no_match_vino.append(ocr_str)
                    if length > 1:
                        break
                is_find = True
                if idx == 0 and compare_res == consts.RESULT_Y:
                    key_right = True
                info_dict[compare_tuple[4]] = compare_res
                if input_str is not None:
                    if idx != 0:
                        if ocr_str is None or ocr_output is None:
                            del info_dict[compare_tuple[0]]
                        else:
                            info_dict[compare_tuple[0]] = ocr_output
                res_set.add(compare_res)
    if not is_find:
        res_set.add(consts.RESULT_N)
        for idx, compare_tuple in enumerate(compare_list):
            info_dict[compare_tuple[4]] = consts.RESULT_NA
            if idx == 0:
                continue
            if compare_tuple[0] in info_dict:
                del info_dict[compare_tuple[0]]
    return is_find and key_right, no_match_vino


def get_ca_compare_info(last_obj):
    compare_info = {}
    individual_info_dict = {}
    for individual_info in json.loads(last_obj.individual_cus_info):
        license_dict = {}

        if individual_info['idType'] in consts.CA_FIRST_ID_FIELD_MAPPING:
            license_en, field_list = consts.CA_FIRST_ID_FIELD_MAPPING[individual_info['idType']]
            field_input = []
            for field in field_list:
                if field in individual_info:
                    field_input.append((field, individual_info.get(field, '')))
            license_dict[license_en] = field_input

        if individual_info.get('secondIdType') in consts.CA_SECOND_ID_FIELD_MAPPING:
            second_license_en, second_field_list = consts.CA_SECOND_ID_FIELD_MAPPING[individual_info['secondIdType']]
            if second_license_en not in license_dict:
                second_field_input = []
                for second_field, write_field in second_field_list:
                    if second_field in individual_info:
                        second_field_input.append((write_field, individual_info.get(second_field, '')))
                license_dict[second_license_en] = second_field_input

        if individual_info['customerType'] == consts.CUSTOMER_TYPE[5]:
            sep_field_input = []
            for sep_field in consts.CA_SEP_FIELD:
                if sep_field in individual_info:
                    sep_field_input.append((sep_field, individual_info.get(sep_field, '')))
            license_dict[consts.BL_EN] = sep_field_input

        if len(license_dict) > 0:
            individual_info_dict.setdefault(individual_info['applicantType'], []).append(license_dict)

    compare_info['individualCusInfo'] = individual_info_dict

    if isinstance(last_obj.corporate_cus_info, str):
        corporate_info_dict = json.loads(last_obj.corporate_cus_info)
        corporate_info = {}
        bl_field_input = []
        for bl_field, write_field in consts.CA_CORPORATE_FIELD:
            bl_field_input.append((write_field, corporate_info_dict.get(bl_field, '')))
        corporate_info[consts.BL_EN] = bl_field_input

        compare_info['corporateCusInfo'] = corporate_info

    if last_obj.vehicle_status == consts.VEHICLE_STATUS[0] and isinstance(last_obj.usedcar_info, str):
        usedcar_info_dict = json.loads(last_obj.usedcar_info)
        usedcar_info = {}

        mvc_field_input = []
        for mvc_field in consts.CA_MVC_FIELD:
            mvc_field_input.append((mvc_field, usedcar_info_dict.get(mvc_field, '')))
        usedcar_info[consts.MVC_EN] = mvc_field_input

        dl_field_input = []
        for dl_field in consts.CA_DL_FIELD:
            dl_field_input.append((dl_field, usedcar_info_dict.get(dl_field, '')))
        usedcar_info[consts.DL_EN] = dl_field_input

        compare_info['usedCarInfo'] = usedcar_info

    return compare_info


def ca_compare_license(license_en, ocr_res_dict, field_list):
    ocr_field, compare_logic, special_expiry_date = consts.CA_COMPARE_FIELD[license_en]

    is_find = False
    special_expiry_date_slice = False
    result_field_list = []
    section_img_info = dict()
    field_img_path_dict = dict()
    ocr_res_str = ocr_res_dict.get(ocr_field)
    if ocr_res_str is not None:
        ocr_res_list = json.loads(ocr_res_str)

        # 副页去除 3/4页去除
        if ocr_field == consts.DL_OCR_FIELD or ocr_field == consts.MVC_OCR_FIELD:
            tmp_list = []
            for res in ocr_res_list:
                if compare_logic['vinNo'][0] in res:
                    tmp_list.append(res)
            ocr_res_list = tmp_list

        length = len(ocr_res_list)

        # 身份证、居住证 过期期限特殊处理
        if special_expiry_date:
            expiry_dates = set()
            expiry_dates_img_path = set()
            key = compare_logic.get('idExpiryDate')[0]
            for ocr_res in ocr_res_list:
                if key in ocr_res:
                    expiry_dates.add(ocr_res[key])
                    expiry_dates_img_path.add(ocr_res.get(consts.IMG_PATH_KEY_2, ''))
        else:
            expiry_dates = set()
            expiry_dates_img_path = set()

        for res_idx in range(length-1, -1, -1):
            if is_find:
                break

            for idx, (name, value) in enumerate(field_list):
                ocr_str = ocr_res_list[res_idx].get(compare_logic[name][0])
                if not isinstance(ocr_str, str):
                    result = consts.RESULT_N
                    ocr_str = empty_str
                else:
                    result = getattr(cp, compare_logic[name][1])(value, ocr_str, **compare_logic[name][2])

                if idx == 0 and result == consts.RESULT_N and length > 1:
                    break

                is_find = True
                section_img_info[consts.SECTION_IMG_PATH_KEY] = ocr_res_list[res_idx].get(consts.SECTION_IMG_PATH_KEY, '')
                section_img_info[consts.ALL_POSITION_KEY] = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY, {})
                if special_expiry_date:
                    section_img_info[consts.SECTION_IMG_PATH_KEY_2] = ocr_res_list[res_idx].get(
                        consts.SECTION_IMG_PATH_KEY_2, '')
                    section_img_info[consts.ALL_POSITION_KEY_2] = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY_2, {})

                # 过期期限特殊处理
                if special_expiry_date and name == 'idExpiryDate' and result == consts.RESULT_N:
                    for expiry_date in expiry_dates:
                        expiry_date_res = getattr(cp, compare_logic[name][1])(value, expiry_date, **compare_logic[name][2])
                        if expiry_date_res == consts.RESULT_Y:
                            ocr_str = expiry_date
                            result = expiry_date_res
                            break

                    if result == consts.RESULT_N:
                        if consts.IMG_PATH_KEY_2 in ocr_res_list[res_idx]:
                            img_path = ocr_res_list[res_idx].get(consts.IMG_PATH_KEY_2, '')
                            special_expiry_date_slice = True
                        else:
                            img_path = expiry_dates_img_path.pop() if len(expiry_dates_img_path) > 0 else empty_str
                    else:
                        img_path = empty_str
                else:
                    img_path = ocr_res_list[res_idx].get(consts.IMG_PATH_KEY, '') if result == consts.RESULT_N else empty_str
                error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value
                result_field_list.append((name, value, result, ocr_str, img_path, error_type))

    if not is_find:
        for name, value in field_list:
            result_field_list.append((name, value, consts.RESULT_N, empty_str, empty_str, ErrorType.NF.value))

    if is_find:
        if special_expiry_date_slice:
            special_section_img_path = section_img_info.get(consts.SECTION_IMG_PATH_KEY_2, '')
            if os.path.exists(special_section_img_path):
                field = 'idExpiryDate'
                special_info = section_img_info.get(consts.ALL_POSITION_KEY_2, {})
                special_section_position = special_info.get(consts.POSITION_KEY, {})
                special_section_angle = special_info.get(consts.ANGLE_KEY, 0)
                try:
                    last_img = img_process(special_section_img_path, special_section_position, special_section_angle)
                except Exception as e:
                    field_img_path_dict[field] = special_section_img_path
                else:
                    pre, suf = os.path.splitext(special_section_img_path)
                    try:
                        res_field = compare_logic[field][0]
                        is_valid, coord_tuple = field_build_coordinates(special_info.get(res_field, {}))
                        if is_valid:
                            save_path = '{0}_{1}{2}'.format(pre, field, suf)
                            field_img = last_img[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :]
                            cv2.imwrite(save_path, field_img)
                            field_img_path_dict[field] = save_path
                        else:
                            field_img_path_dict[field] = special_section_img_path
                    except Exception as e:
                        field_img_path_dict[field] = special_section_img_path

        section_img_path = section_img_info.get(consts.SECTION_IMG_PATH_KEY, '')
        if os.path.exists(section_img_path):
            failed_field = []
            base_img_path = empty_str
            for name, _, result, _, img_path, _ in result_field_list:
                if result == consts.RESULT_N:
                    if special_expiry_date_slice and name == 'idExpiryDate':
                        continue
                    failed_field.append(name)
                    if base_img_path == empty_str:
                        base_img_path = img_path
            if len(failed_field) > 0:
                info = section_img_info.get(consts.ALL_POSITION_KEY, {})
                section_position = info.get(consts.POSITION_KEY, {})
                section_angle = info.get(consts.ANGLE_KEY, 0)
                try:
                    last_img = img_process(section_img_path, section_position, section_angle)
                except Exception as e:
                    for field in failed_field:
                        field_img_path_dict[field] = base_img_path
                else:
                    pre, suf = os.path.splitext(section_img_path)
                    for field in failed_field:
                        try:
                            if license_en == consts.PP_EN:
                                res_field = consts.PP_SLICE_MAP[field]
                            else:
                                res_field = compare_logic[field][0]
                            is_valid, coord_tuple = field_build_coordinates(info.get(res_field, {}))
                            if is_valid:
                                save_path = '{0}_{1}{2}'.format(pre, field, suf)
                                field_img = last_img[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :]
                                cv2.imwrite(save_path, field_img)
                                field_img_path_dict[field] = save_path
                            else:
                                field_img_path_dict[field] = base_img_path
                        except Exception as e:
                            field_img_path_dict[field] = base_img_path

    return result_field_list, field_img_path_dict


def ca_compare_process(compare_info, ocr_res_dict):
    # individualCusInfo
    # corporateCusInfo
    # usedCarInfo
    compare_result = []
    total_fields = 0
    failed_count = 0

    for info_key, info_value in compare_info.items():
        if info_key == 'individualCusInfo':
            for idx, license_list in info_value.items():
                for license_dict in license_list:
                    for license_en, field_list in license_dict.items():
                        result_field_list, field_img_path_dict = ca_compare_license(license_en, ocr_res_dict, field_list)
                        for name, value, result, ocr_str, img_path, error_type in result_field_list:
                            total_fields += 1
                            if result == consts.RESULT_N:
                                failed_count += 1
                            compare_result.append(
                                {
                                    consts.HEAD_LIST[0]: info_key,
                                    consts.HEAD_LIST[1]: idx,
                                    consts.HEAD_LIST[2]: license_en,
                                    consts.HEAD_LIST[3]: name,
                                    consts.HEAD_LIST[4]: value,
                                    consts.HEAD_LIST[5]: ocr_str,
                                    consts.HEAD_LIST[6]: result,
                                    consts.HEAD_LIST[7]: field_img_path_dict.get(name, empty_str),
                                    consts.HEAD_LIST[8]: img_path,
                                    consts.HEAD_LIST[9]: error_type,
                                }
                            )
        else:
            for license_en, field_list in info_value.items():
                result_field_list, field_img_path_dict = ca_compare_license(license_en, ocr_res_dict, field_list)
                for name, value, result, ocr_str, img_path, error_type in result_field_list:
                    total_fields += 1
                    if result == consts.RESULT_N:
                        failed_count += 1
                    compare_result.append(
                        {
                            consts.HEAD_LIST[0]: info_key,
                            consts.HEAD_LIST[1]: "0",
                            consts.HEAD_LIST[2]: license_en,
                            consts.HEAD_LIST[3]: name,
                            consts.HEAD_LIST[4]: value,
                            consts.HEAD_LIST[5]: ocr_str,
                            consts.HEAD_LIST[6]: result,
                            consts.HEAD_LIST[7]: field_img_path_dict.get(name, empty_str),
                            consts.HEAD_LIST[8]: img_path,
                            consts.HEAD_LIST[9]: error_type,
                        }
                    )
    return compare_result, total_fields, failed_count


def ca_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict):
    start_time = datetime.now()

    try:
        # 比对逻辑
        compare_info = get_ca_compare_info(last_obj)
        compare_result, total_fields, failed_count = ca_compare_process(compare_info, ocr_res_dict)
        compare_log.info('{0} [CA] [compare success] [entity={1}] [id={2}] [ocr_res_id={3}] [result={4}]'.format(
            log_base, application_entity, application_id, ocr_res_id, compare_result))
    except Exception as e:
        compare_log.error('{0} [CA] [compare error] [entity={1}] [id={2}] [ocr_res_id={3}] '
                          '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id,
                                               traceback.format_exc()))
    else:
        # 将比对结果写入数据库
        try:
            result_table = HILCACompareResult if application_entity == consts.HIL_PREFIX else AFCCACompareResult
            res_obj = result_table.objects.filter(application_id=application_id).first()
            if res_obj is None:
                res_obj = result_table()
                res_obj.application_id = application_id
            res_obj.compare_count = total_fields
            res_obj.failed_count = failed_count
            res_obj.is_finish = failed_count == 0
            res_obj.version = '{0}{1}{2}'.format(consts.INFO_SOURCE[0], consts.SPLIT_STR, last_obj.application_version)
            # res_obj.reason1_count = reason1_count
            res_obj.result = json.dumps(compare_result)
            res_obj.update_time = start_time
            res_obj.save()
            compare_log.info('{0} [CA] [result save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format(
                log_base, application_entity, application_id, ocr_res_id))
        except Exception as e:
            compare_log.error('{0} [CA] [result save error] [entity={1}] [id={2}] [ocr_res_id={3}] '
                              '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id,
                                                   traceback.format_exc()))

    compare_failed = False
    application_link = '{0}/showList/showList?entity={1}&scheme={2}&case_id={3}'.format(
        conf.BASE_URL, application_entity, consts.COMPARE_DOC_SCHEME_LIST[0], application_id)

    # 比对信息
    try:
        comparison_res = OrderedDict({
            'OCR_Input': {
                'uniqSeq': last_obj.uniq_seq,
                'applicationId': application_id,
                'applicationEntity': application_entity,
                'applicationVersion': last_obj.application_version,
                'vehicleStatus': last_obj.vehicle_status,
                'wholeResult': 'N',
                'wholeResultMessage': empty_str,
                'applicationLink': application_link.replace('&', '&'),
            }
        })

        res_set = set()

        # is_sep = True if last_obj.customer_type == consts.CUSTOMER_TYPE[5] else False

        individual_cus_info_list = json.loads(last_obj.individual_cus_info)
        order_individual_cus_info_list = []
        for individual_cus_info in individual_cus_info_list:
            order_individual_cus_info = get_order_dict(individual_cus_info, consts.IN_ORDER)

            cus_type = order_individual_cus_info.get('customerType')

            # 获取sep下营业执照法人代表
            if cus_type == consts.CUSTOMER_TYPE[5]:
                sep_name = order_individual_cus_info.get('customerChineseName')
                if isinstance(sep_name, str):
                    sep_name = sep_name.strip()
                    if sep_name == empty_str:
                        sep_name = None
            else:
                sep_name = None

            # 个人信息证件
            id_type = order_individual_cus_info.get('idType')
            if id_type not in consts.ID_TYPE_COMPARE:
                do_not_compare(order_individual_cus_info, consts.ITPRC)
            else:
                ocr_field, compare_list, has_expiry_date = consts.ID_TYPE_COMPARE.get(id_type)
                field_compare(order_individual_cus_info, ocr_res_dict, ocr_field, compare_list, res_set,
                              has_expiry_date=has_expiry_date)

            # 第二证件
            second_id_type = order_individual_cus_info.get('secondIdType')
            if second_id_type is not None:
                if second_id_type not in consts.SECOND_ID_TYPE_COMPARE:
                    do_not_compare(order_individual_cus_info, consts.SECOND_ITPRC)
                else:
                    second_ocr_field, second_compare_list = consts.SECOND_ID_TYPE_COMPARE.get(second_id_type)
                    field_compare(order_individual_cus_info, ocr_res_dict, second_ocr_field,
                                  second_compare_list, res_set)

                # 姓名比对
                second_id_res = order_individual_cus_info.pop(consts.SECOND_ID_RES, consts.RESULT_NA)
                if second_id_res == consts.RESULT_Y:
                    second_id_num = order_individual_cus_info.get(consts.SECOND_ID_FIELD)
                    name = order_individual_cus_info.get(consts.NAME_FIELD)
                    if isinstance(second_id_num, str) and isinstance(name, str):
                        second_ocr_field, second_compare_list, _ = consts.ID_TYPE_COMPARE.get(second_id_type)
                        name_right = name_check(ocr_res_dict, second_ocr_field, second_compare_list, second_id_num, name)
                        if not name_right:
                            res_set.add(consts.RESULT_N)
                            second_id_res = consts.RESULT_N
                            order_individual_cus_info[consts.SECOND_ID_FIELD] = '{0}-{1}'.format(second_id_num, name)

                # 重新排列
                new_dict = OrderedDict({})
                for key, value in order_individual_cus_info.items():
                    new_dict[key] = value
                    if key == consts.ID_RES:
                        new_dict[consts.SECOND_ID_RES] = second_id_res
                order_individual_cus_info = new_dict

            # sep营业执照
            if cus_type == consts.CUSTOMER_TYPE[5]:
                field_compare(order_individual_cus_info, ocr_res_dict, consts.BL_OCR_FIELD, consts.TCSEP, res_set,
                              sep_name=sep_name, capital_ignore=True)

            order_individual_cus_info_list.append(order_individual_cus_info)

        comparison_res['OCR_Input']['individualCusInfo'] = order_individual_cus_info_list

        if last_obj.vehicle_status == consts.VEHICLE_STATUS[0] and last_obj.usedcar_info is not None:
            usedcar_info = json.loads(last_obj.usedcar_info)
            order_usedcar_info = get_order_dict(usedcar_info, consts.UC_ORDER)

            mvc_find, mvc_vinos = usedcar_info_compare(order_usedcar_info, ocr_res_dict, consts.MVC_OCR_FIELD,
                                                       consts.PCUSD_MVC, res_set)

            # if order_usedcar_info[consts.PCUSD_MVC[0][0] + 'Result'] == consts.RESULT_Y:
            dl_find, dl_vinos = usedcar_info_compare(order_usedcar_info, ocr_res_dict, consts.DL_OCR_FIELD,
                                                     consts.PCUSD_DL, res_set)

            if mvc_find is True and dl_find is False:
                vino = dl_vinos[-1] if len(dl_vinos) > 0 else empty_str
                order_usedcar_info[consts.PCUSD_MVC[0][0]] = '{0}-{1} {2} {3}-{4}'.format(
                    consts.PREFIX_MVC, consts.RESULT_Y, consts.SPLIT, consts.PREFIX_DL, vino)
                order_usedcar_info[consts.PCUSD_MVC[0][4]] = consts.RESULT_N
            elif mvc_find is False and dl_find is True:
                vino = mvc_vinos[-1] if len(mvc_vinos) > 0 else empty_str
                order_usedcar_info[consts.PCUSD_MVC[0][0]] = '{0}-{1} {2} {3}-{4}'.format(
                    consts.PREFIX_MVC, vino, consts.SPLIT, consts.PREFIX_DL, consts.RESULT_Y)
                order_usedcar_info[consts.PCUSD_MVC[0][4]] = consts.RESULT_N
            elif mvc_find is False and dl_find is False:
                if len(mvc_vinos) == 0 and len(dl_vinos) == 0:
                    order_usedcar_info[consts.PCUSD_MVC[0][0]] = None
                    order_usedcar_info[consts.PCUSD_MVC[0][4]] = consts.RESULT_NA
                else:
                    mvc_vino = mvc_vinos[-1] if len(mvc_vinos) > 0 else empty_str
                    dl_vino = dl_vinos[-1] if len(dl_vinos) > 0 else empty_str
                    vino = '{0}-{1} {2} {3}-{4}'.format(
                        consts.PREFIX_MVC, mvc_vino, consts.SPLIT, consts.PREFIX_DL, dl_vino)
                    order_usedcar_info[consts.PCUSD_MVC[0][0]] = vino
                    order_usedcar_info[consts.PCUSD_MVC[0][4]] = consts.RESULT_N

            comparison_res['OCR_Input']['usedCarInfo'] = order_usedcar_info

        if last_obj.corporate_cus_info is not None:
            corporate_cus_info = json.loads(last_obj.corporate_cus_info)
            order_corporate_cus_info = get_order_dict(corporate_cus_info, consts.CO_ORDER)
            field_compare(order_corporate_cus_info, ocr_res_dict, consts.BL_OCR_FIELD, consts.TCCOR, res_set)

            comparison_res['OCR_Input']['corporateCusInfo'] = order_corporate_cus_info

        comparison_res['OCR_Input'][
            'wholeResult'] = consts.RESULT_N if consts.RESULT_N in res_set or consts.RESULT_NA in res_set else consts.RESULT_Y

    except Exception as e:
        compare_failed = True
        compare_log.error('{0} [CA] [compare error] [entity={1}] [id={2}] [ocr_res_id={3}] [error={4}]'.format(
            log_base, application_entity, application_id, ocr_res_id, traceback.format_exc()))
    else:
        compare_log.info('{0} [CA] [compare success] [entity={1}] [id={2}] [ocr_res_id={3}] [compare_res={4}]'.format(
            log_base, application_entity, application_id, ocr_res_id, comparison_res))

        is_gcap_send = Configs.objects.filter(id=1).first()
        if is_gcap_send is not None and is_gcap_send.value == 'N':
            compare_log.info('{0} [CA] [gcap closed] [entity={1}] [id={2}] [ocr_res_id={3}]'.format(
                log_base, application_entity, application_id, ocr_res_id))
            return

        # 时间延迟
        send_time = last_obj.create_time + timedelta(seconds=15)
        while datetime.now() < send_time:
            compare_log.info('{0} [CA] [time wait 5s] [entity={1}] [id={2}] [ocr_res_id={3}]'.format(
                log_base, application_entity, application_id, ocr_res_id))
            time.sleep(5)

        # 将比对结果发送GCAP
        try:
            data = gcap.dict_to_xml(comparison_res)
        except Exception as e:
            compare_log.error('{0} [CA] [dict to xml failed] [entity={1}] [id={2}] [ocr_res_id={3}] [error={4}]'.format(
                log_base, application_entity, application_id, ocr_res_id, traceback.format_exc()))
        else:
            try:
                for times in range(consts.RETRY_TIMES):
                    try:
                        res_text = gcap.send(data)
                    except Exception as e:
                        gcap_exc = str(e)
                    else:
                        break
                else:
                    raise GCAPException(gcap_exc)
            except Exception as e:
                compare_log.error('{0} [CA] [gcap failed] [entity={1}] [id={2}] [ocr_res_id={3}] [error={4}]'.format(
                    log_base, application_entity, application_id, ocr_res_id, traceback.format_exc()))
            else:
                compare_log.info('{0} [CA] [gcap success] [entity={1}] [id={2}] [ocr_res_id={3}] [response={4}]'.format(
                    log_base, application_entity, application_id, ocr_res_id, res_text))
                compare_log.info('{0} [CA] [task success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format(
                    log_base, application_entity, application_id, ocr_res_id))

        # report
        try:
            end_time = datetime.now()
            if compare_failed:
                successful_at_this_level = False
                failure_reason = 'Compare process error'
                total_fields = 0
            else:
                successful_at_this_level = True if comparison_res['OCR_Input'][
                                                       'wholeResult'] == consts.RESULT_Y else False
                field_failed = {
                    'individualCusInfo': [],
                    'corporateCusInfo': [],
                    'usedCarInfo': []
                }

                individual_list = comparison_res.get('OCR_Input', {}).get('individualCusInfo', [])
                total_fields = 0

                for individual in individual_list:

                    field_list = []
                    if individual.get('idType') in consts.ID_TYPE_COMPARE:
                        total_fields += 4
                        if not successful_at_this_level:
                            for field_name, _, _, _, result_field in consts.ITPRC:
                                if individual.get(result_field) != consts.RESULT_Y:
                                    field_list.append(field_name)

                    if individual.get('secondIdType') in consts.SECOND_ID_TYPE_COMPARE:
                        total_fields += 1
                        if not successful_at_this_level:
                            if individual.get(consts.SECOND_ID_RES) != consts.RESULT_Y:
                                field_list.append(consts.SECOND_ID_FIELD)

                    if individual.get('customerType') == consts.CUSTOMER_TYPE[5]:
                        total_fields += 3
                        if not successful_at_this_level:
                            for field_name, _, _, _, result_field in consts.TCSEP:
                                if individual.get(result_field) != consts.RESULT_Y:
                                    field_list.append(field_name)

                    if len(field_list) > 0:
                        field_failed['individualCusInfo'].append(';'.join(field_list))

                corporate_res = comparison_res.get('OCR_Input', {}).get('corporateCusInfo')
                if corporate_res is not None:
                    total_fields += 8
                    if not successful_at_this_level:
                        corporate_field_list = []
                        for field_name, _, _, _, result_field in consts.TCCOR:
                            if corporate_res.get(result_field) != consts.RESULT_Y:
                                corporate_field_list.append(field_name)
                        if len(corporate_field_list) > 0:
                            field_failed['corporateCusInfo'].append(';'.join(corporate_field_list))

                used_car_res = comparison_res.get('OCR_Input', {}).get('usedCarInfo')
                if used_car_res is not None:
                    total_fields += 3
                    if not successful_at_this_level:
                        used_car_field_list = []
                        for field_name, _, _, _, result_field in consts.PCUSD_MVC:
                            if used_car_res.get(result_field) != consts.RESULT_Y:
                                used_car_field_list.append(field_name)
                        if len(used_car_field_list) > 0:
                            field_failed['usedCarInfo'].append(';'.join(used_car_field_list))

                if not successful_at_this_level:
                    reason_list = []
                    for key, value in field_failed.items():
                        if len(value) > 0:
                            value_str = json.dumps(value)
                            reason_list.append('{0}: {1}'.format(key, value_str))
                    failure_reason = '、'.join(reason_list)

                else:
                    failure_reason = empty_str

            request_trigger = RequestTrigger.SUBMITING.value if ocr_res_id is None else RequestTrigger.UPLOADING.value
            report_class = HILCompareReport if application_entity == consts.HIL_PREFIX else AFCCompareReport
            report_class.objects.create(
                case_number=application_id,
                request_team=RequestTeam.ACCEPTANCE.value,
                request_trigger=request_trigger,
                transaction_start=start_time,
                transaction_end=end_time,
                successful_at_this_level=successful_at_this_level,
                failure_reason=failure_reason,
                process_name=ProcessName.CACOMPARE.value,
                total_fields=total_fields,
                workflow_name=last_obj.customer_type,
            )
            compare_log.info(
                '{0} [CA] [report save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format(
                    log_base, application_entity, application_id, ocr_res_id))
        except Exception as e:
            compare_log.error('{0} [CA] [report save error] [entity={1}] [id={2}] [ocr_res_id={3}] '
                              '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id,
                                                   traceback.format_exc()))


def get_se_cms_compare_info_auto(last_obj, application_entity, auto=True):
    cms_info = json.loads(last_obj.content)

    compare_info = {}

    individual_info_dict = {}
    main_role_info = {}
    company_info_list = []

    dealer_name_list = cms_info.get('dealerName', '').split()
    dealer_name = '' if len(dealer_name_list) == 0 else dealer_name_list[-1]

    # 个人信息证件------------------------------------------------------------------------------------------------------
    # is_cdfl = True  # 车贷分离
    is_cdfl_bo = False  # 车贷分离,主借
    is_cdfl_co = False  # 车贷分离,共借
    # province = cms_info.get('province', '')
    for individual_info in cms_info.get('applicantInformation', []):
        all_id_num = []

        license_dict = {}

        customer_name = individual_info.get('name', '').strip()
        legal_name = individual_info.get('legalRepName', '')
        establishment_date = individual_info.get('establishmentDate', '')
        # date_of_birth = individual_info.get('dateOfBirth', '')

        # 车贷分离判断
        is_corporate = individual_info.get('customersubType', '') == 'Corporate'
        if individual_info['applicantType'] == consts.APPLICANT_TYPE_ORDER[1] and is_corporate:
            is_cdfl_co = True
        if individual_info['applicantType'] == consts.APPLICANT_TYPE_ORDER[0] and not is_corporate:
            is_cdfl_bo = True

        for id_info in individual_info.get('IDInformation', []):
            if id_info.get('idType') in consts.SE_CMS_FIRST_ID_FIELD_MAPPING:
                license_en, is_prc = consts.SE_CMS_FIRST_ID_FIELD_MAPPING[id_info['idType']]
                # ['customerName', 'idNum', 'dateOfBirth', 'idExpiryDate', 'hukouProvince']
                id_num = decode_des(id_info.get('idNum', ''), des_key)
                field_input = [('customerName', customer_name), ('idNum', id_num),
                               ('idExpiryDate', id_info.get('idExpiryDate', ''))]
                # if is_prc:
                #     field_input.append(('hukouProvince', province))
                #     field_input.append(('真伪', consts.IC_RES_MAPPING.get(1)))
                license_dict[license_en] = field_input
                all_id_num.append(id_num)
            # 营业执照 --------------------------------------------------------------------------------------------------
            elif id_info.get('idType') in ['Unified Social Credit Code', 'Tax Number', 'Business License Number']:
                # ['companyName', 'legalRepName', 'businessLicenseNo', 'organizationCreditCode',
                #  'taxRegistrationCertificateNo', 'establishmentDate', 'businessLicenseDueDate']
                id_num = decode_des(id_info.get('idNum', ''), des_key)
                # bl_field_input = [
                #     ('companyName', customer_name),
                #     ('legalRepName', legal_name),
                #     ('businessLicenseNo', id_num),
                #     ('organizationCreditCode', id_num),
                #     ('taxRegistrationCertificateNo', id_num),
                #     ('businessLicenseDueDate', id_info.get('idExpiryDate', '')),
                # ]

                if is_corporate:
                    company_info_list.append((customer_name, id_num, legal_name))
                # else:
                #     bl_field_input.append(('establishmentDate', establishment_date))

                # license_dict[consts.BL_EN] = bl_field_input
                all_id_num.append(id_num)

        # SME营业执照---------------------------------------------------------------------------------------------------
        # if individual_info.get('customersubType', '').startswith('Self Employed'):
        #     sep_field_input = [
        #         ('legalRepName', customer_name),
        #         ('businessLicenseDueDate', ''),
        #     ]
        #     license_dict[consts.SME_BL_EN] = sep_field_input

        if len(all_id_num) > 0:
            main_role_info.setdefault(individual_info['applicantType'], []).append(
                (customer_name, '、'.join(all_id_num), all_id_num[0])
            )

        if len(license_dict) > 0:
            individual_info_dict.setdefault(individual_info['applicantType'], []).append(license_dict)

    compare_info['applicantInformation'] = individual_info_dict

    main_name = main_id_all = main_id = ''
    for applicant_type in consts.APPLICANT_TYPE_ORDER:
        if applicant_type in main_role_info:
            main_name, main_id_all, main_id = main_role_info[applicant_type][0]
            # hmh_name, _, hmh_id = main_role_info[applicant_type][0]
            break

    # co_name = co_id = bo_name = bo_id = ''
    # if is_cdfl:
    #     co_name, _, co_id = main_role_info[consts.APPLICANT_TYPE_ORDER[1]][0]
    #     bo_name, _, bo_id = main_role_info[consts.APPLICANT_TYPE_ORDER[0]][0]

    co_name = co_id = bo_name = bo_id = ''
    is_cdfl = is_cdfl_bo and is_cdfl_co
    if is_cdfl:
        if len(main_role_info.get(consts.APPLICANT_TYPE_ORDER[1], [])) > 0:
            co_name, _, co_id = main_role_info[consts.APPLICANT_TYPE_ORDER[1]][0]
        else:
            co_name = co_id = ''
        if len(main_role_info.get(consts.APPLICANT_TYPE_ORDER[0], [])) > 0:
            bo_name, _, bo_id = main_role_info[consts.APPLICANT_TYPE_ORDER[0]][0]
        else:
            bo_name = bo_id = ''

    # dda_name_list = []
    # dda_num_list = []
    if len(company_info_list) > 0:
        # tmp_idx = 1
        company_info = company_info_list[0]
    else:
        # tmp_idx = 0
        company_info = None

    # for applicant_type in consts.APPLICANT_TYPE_ORDER[tmp_idx: tmp_idx + 2]:
    #     if applicant_type in main_role_info:
    #         for dda_name_part, _, dda_num_part in main_role_info[applicant_type]:
    #             dda_name_list.append(dda_name_part)
    #             dda_num_list.append(dda_num_part)
    # dda_name = '、'.join(dda_name_list)
    # dda_num = '、'.join(dda_num_list)
    # del main_role_info

    vehicle_info = {}
    vehicle_field_input = []
    vehicle_status = cms_info.get('vehicleStatus', '')
    first_submission_date = cms_info.get('submissionDate', '')
    vin_no = cms_info.get('vehicleInformation', {}).get('vinNo', '')
    amount = str(cms_info.get('financialInformation', {}).get('vehiclePrice', '0.0'))
    # 新车发票----------------------------------------------------------------------------------------------------------
    if vehicle_status == 'New':
        vehicle_field_input.append(('vinNo', vin_no))
        vehicle_field_input.append(('dealer', '、'.join([dealer_name, cms_info.get('fapiaoIssuerDealer', '')])))
        vehicle_field_input.append(('vehicleTransactionAmount', amount))

        if isinstance(company_info, tuple):
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0]))  # 车贷分离
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1]))  # 车贷分离
        else:
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name))  # 车贷分离
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id))  # 车贷分离
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[2], first_submission_date))
        # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[3], consts.SE_STAMP_VALUE))
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[4], consts.SE_FPL_VALUE))
        bhsj = float(amount) / 1.13
        # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[5], consts.SPLIT_STR.join([
        #     format(bhsj, '.2f'),
        #     format(float(amount) - bhsj, '.2f'),
        #     consts.RESULT_Y
        # ])))
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[7], format(bhsj, '.2f')))
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[8], format(float(amount) - bhsj, '.2f')))
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[9], consts.RESULT_Y))
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[6], consts.SE_LAYOUT_VALUE))
        vehicle_info[consts.MVI_EN] = vehicle_field_input
    # 二手车发票、交易凭证、绿本------------------------------------------------------------------------------------------
    # else:
    #     gb_field_input = [
    #         ('vinNo', vin_no),
    #     ]
    #     gb34_field_input = []
    #     jypz_field_input = []
    #     vehicle_field_input.append(('vinNo', vin_no))
    #     vehicle_field_input.append(('vehicleTransactionAmount', amount))
    #     if isinstance(company_info, tuple):
    #         vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0]))  # 车贷分离
    #         vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1]))  # 车贷分离
    #         jypz_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0]))  # 车贷分离
    #         jypz_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1]))  # 车贷分离
    #         gb34_field_input.append((consts.SE_GB_USED_FIELD[0], co_name if is_cdfl else company_info[0]))  # 车贷分离
    #         gb34_field_input.append((consts.SE_GB_USED_FIELD[1], co_id if is_cdfl else company_info[1]))  # 车贷分离
    #     else:
    #         vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name))  # 车贷分离
    #         vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id_all))  # 车贷分离
    #         jypz_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name))  # 车贷分离
    #         jypz_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id_all))  # 车贷分离
    #         gb34_field_input.append((consts.SE_GB_USED_FIELD[0], co_name if is_cdfl else main_name))  # 车贷分离
    #         gb34_field_input.append((consts.SE_GB_USED_FIELD[1], co_id if is_cdfl else main_id_all))  # 车贷分离
    #     gb34_field_input.append((consts.SE_GB_USED_FIELD[2], first_submission_date))
    #     vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[2], first_submission_date))
    #     # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[3], consts.SE_STAMP_VALUE))
    #     jypz_field_input.append(('dealerName', dealer_name))
    #     jypz_field_input.append(('vinNo', vin_no))
    #     jypz_field_input.append(('vehicleTransactionAmount', amount))
    #     jypz_field_input.append((consts.SE_GB_USED_FIELD[-1], first_submission_date))
    #
    #     vehicle_info[consts.MVC_EN] = gb_field_input
    #     vehicle_info[consts.MVC34_EN] = gb34_field_input
    #     if not detect_list[0]:
    #         vehicle_info[consts.UCI_EN] = vehicle_field_input
    #     if not detect_list[1]:
    #         vehicle_info[consts.JYPZ_EN] = jypz_field_input
    #     if detect_list[0] and detect_list[1]:
    #         vehicle_info[consts.UCI_EN] = vehicle_field_input
        compare_info['vehicleInfo'] = vehicle_info

    # 银行卡-------------------------------------------------------------------------------------------------------
    bank_info = {}
    bank_name = cms_info.get('bankAccountDetails', {}).get('bankName', '')
    account_no = decode_des(cms_info.get('bankAccountDetails', {}).get('accountNo', ''), des_key)
    account_holder_name = cms_info.get('bankAccountDetails', {}).get('accountHolderName', '')
    is_gsyh = True if '工商' in bank_name else False

    if isinstance(company_info, tuple) and company_info[0] == account_holder_name:
        pass
    else:
        bank_field_input = [
            ('accountNo', account_no),
            ('bankName', bank_name),
            ('type', consts.BC_TYPE_VALUE),
        ]
        bank_info[consts.BC_EN] = bank_field_input

    # DDA------------------------------------------------------------------------------------------------------------
    # if is_gsyh or not detect_list[-1]:
    #     dda_field_input = [
    #         ('applicationId(1)', last_obj.application_id),
    #         ('applicationId(2)', last_obj.application_id),
    #         ('bankName', bank_name),
    #         ('companyName', consts.HIL_COMPANY_NAME if application_entity in consts.HIL_SET else consts.AFC_COMPANY_NAME),
    #         ('customerName', dda_name),
    #         ('idNum', dda_num),
    #         ('accountHolderName', account_holder_name),
    #         ('accountNo', account_no),
    #     ]
    #     bank_info[consts.DDA_EN] = dda_field_input
    if len(bank_info) > 0:
        compare_info['bankInfo'] = bank_info

    # 银行流水 --------------------------------------------------------------------
    if cms_info.get('autoApprovedDetails', {}).get('aaType', '') in ['CAA1', 'CAA2'] and \
            cms_info.get('autoApprovedDetails', {}).get('PolicyComments', '') != '此申请无需提供流水':
        date_timedelta = 60 if auto else 90
        bs_role_list = []
        for applicant_type in consts.APPLICANT_TYPE_ORDER[:2]:
            if applicant_type in main_role_info:
                for bs_role, _, _ in main_role_info[applicant_type]:
                    bs_role_list.append(bs_role)

        bs_info = dict()
        bs_field_input = [
            (consts.SE_BS_FIELD[0], bs_role_list),
            (consts.SE_BS_FIELD[1], first_submission_date),
            (consts.SE_BS_FIELD[2], date_timedelta),
        ]

        dbr_bs_role_list = []
        for dbr_bs_role, _, _ in main_role_info.get(consts.APPLICANT_TYPE_ORDER[2], []):
            dbr_bs_role_list.append(dbr_bs_role)

        if len(dbr_bs_role_list) >= 1:
            bs_field_input.extend([
                (consts.SE_BS_FIELD[3], dbr_bs_role_list[0]),
                (consts.SE_BS_FIELD[4], first_submission_date),
                (consts.SE_BS_FIELD[5], date_timedelta),
            ])
            if len(dbr_bs_role_list) >= 2:
                bs_field_input.extend([
                    (consts.SE_BS_FIELD[6], dbr_bs_role_list[1]),
                    (consts.SE_BS_FIELD[7], first_submission_date),
                    (consts.SE_BS_FIELD[8], date_timedelta),
                ])
        bs_info[consts.BS_EN] = bs_field_input
        compare_info['Bank Statement'] = bs_info

    # 抵押登记豁免函----------------------------------------------------------------------------------------------------
    other_info = {}
    full_no = cms_info.get('settlemnetVerification', {}).get('applicationNo', '')
    if cms_info.get('mortgageType', '') == 'Mortgage Free' or cms_info.get('mortgageType', '') == 'MortgageFree':
        hmh_field_input = [
            (consts.SE_HMH_FIELD[0], main_name),
            (consts.SE_HMH_FIELD[1], main_id),
            (consts.SE_HMH_FIELD[2], full_no),
            (consts.SE_HMH_FIELD[3], cms_info.get('financeCompany', '')),
            (consts.SE_HMH_FIELD[4], consts.SE_STAMP_VALUE),
        ]
        other_info[consts.HMH_EN] = hmh_field_input

    # ASP -------------------------------------------------------------------------------------------------------
    asp_list = []
    gzs_status = consts.GZS_STATUS[1]
    gzs_list = [gzs_status]
    gzs_price = '0.00'
    is_asp = False
    # insurance_price = None
    if str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.00')) != '0.00':
        is_asp = True
        # for asp_info in cms_info.get('associatedServices', []):
        for asp_info in cms_info.get('associatedServices', {}).get('SubassociatedServices', []):
            tmp_asp_name = asp_info.get('associatedServices')
            if isinstance(tmp_asp_name, str) and len(tmp_asp_name) > 0:
                if gzs_status == consts.GZS_STATUS[1] and tmp_asp_name.find(consts.GZS_NAME) != -1:
                    gzs_status = consts.GZS_STATUS[2]
                    gzs_price = asp_info.get('price', '0.00')
                asp_list.append(
                    (
                        tmp_asp_name,
                        asp_info.get('price', '0.00'),
                        asp_info.get('financed', '0.00')
                    )
                )
                # 保单费合计
                # if tmp_asp_name.find('机动车辆保险') != -1:
                #     insurance_price = asp_info.get('price', '0.00')

        fin_total = 0
        # fin_total_tmp = cms_info.get('associatedServices', {}).get('financed total', '0.00')
        # fin_total = '0.00' if fin_total_tmp.strip() == '' else fin_total_tmp
        for asp_name, _, asp_fin in asp_list:
            if gzs_status == consts.GZS_STATUS[2] and asp_name.find(consts.GZS_NAME) == -1:
                gzs_status = consts.GZS_STATUS[0]
            fin_total += float(asp_fin)
        asp_list.append(
            (
                consts.ASP_SUM_NAME,
                '',
                # fin_total,
                format(fin_total, '.2f'),
            )
        )

        # CMS Vehicle Price / 1.13 * 10 %
        gzs_list = [gzs_status]
        if gzs_status != consts.GZS_STATUS[1]:
            gzs_value = float(amount) * 0.1 / 1.13
            gzs_list.append(gzs_value)
            gzs_list.append(float(gzs_price))

    # 保单 -----------------------------------------------------------------------------------------------------------
    # is_insurance = 0
    # fp_campaign = cms_info.get('fpCampaign', '')
    fp_group = cms_info.get('fpGroup', '')
    # insurance_type = cms_info.get('insuranceDetails', {}).get('insuranceType', '')
    # if insurance_type == 'Waive Insurance' and isinstance(insurance_price, str):
    #     is_insurance = 1
    # elif insurance_type == 'Comprehensive Insurance':
    #     is_insurance = 2
    # if is_insurance != 0:
    #     if fp_campaign.find('OCU') == -1:
    #         ssx_amount = amount
    #     else:
    #         ssx_amount = format(float(amount) * 0.8, '.2f')
    #     if fp_campaign.find('Joy_Plus') == -1 or fp_campaign.find('JoyPlus') == -1:
    #         dszx_amount = '200000'
    #     else:
    #         dszx_amount = '500000'
    #     bd_field_input = [
    #         (consts.SE_BD_FIELD[0], [co_name, bo_name] if is_cdfl else [main_name, ]),  # 车贷分离
    #         (consts.SE_BD_FIELD[1], [co_id, bo_id] if is_cdfl else [main_id, ]),  # 车贷分离
    #         (consts.SE_BD_FIELD[2], vin_no),
    #         (consts.SE_BD_FIELD[3], ssx_amount),
    #         (consts.SE_BD_FIELD[4], dszx_amount),
    #         (consts.SE_BD_FIELD[5], consts.JDMPV_VALUE),
    #         (consts.SE_BD_FIELD[6], cms_info.get('insuranceDetails', {}).get('startDate', '')),
    #         (consts.SE_BD_FIELD[7], cms_info.get('insuranceDetails', {}).get('endDate', '')),
    #         (consts.SE_BD_FIELD[8], consts.SE_STAMP_VALUE),
    #         (consts.SE_BD_FIELD[9], consts.SE_DYSYR_VALUE),
    #     ]
    #     if is_insurance == 1:
    #         bd_field_input.append((consts.SE_BD_FIELD[10], insurance_price))
    #     other_info[consts.BD_EN] = bd_field_input

    if len(other_info) > 0:
        compare_info['other'] = other_info

    schedule_list = []
    total_amount = 0
    for schedule_dict in cms_info.get('paymentSchedule', []):
        tmp_str = "{1}{0}{2}".format(consts.SPLIT_STR, str(schedule_dict.get('no', '')),
                                     str(schedule_dict.get('grossRentalAmount', '')))
        schedule_list.append(tmp_str)
        total_amount += float(schedule_dict.get('grossRentalAmount', '0.0'))
    schedule_list_str = consts.SCHEDULE_SPLIT_STR.join(schedule_list)

    online_sign = cms_info.get('contractSource', 'Online Sign') == 'Online Sign'

    contract_info = {}
    if application_entity in consts.HIL_SET:
        # HIL合同  售后回租合同 --------------------------------------------------------------------------------------
        hil_contract_1_input = [
            (consts.SE_HIL_CON_1_FIELD[0], [full_no] if online_sign else full_no),
            (consts.SE_HIL_CON_1_FIELD[1], full_no),
            (consts.SE_HIL_CON_1_FIELD[2], vin_no),
            (consts.SE_HIL_CON_1_FIELD[3], dealer_name),
            (consts.SE_HIL_CON_1_FIELD[4], amount),
            (consts.SE_HIL_CON_1_FIELD[5], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))),
            (consts.SE_HIL_CON_1_FIELD[6], str(cms_info.get('terms', '0'))),
            (consts.SE_HIL_CON_1_FIELD[7], schedule_list_str),
            (consts.SE_HIL_CON_1_FIELD[11], account_no),
            (consts.SE_HIL_CON_1_FIELD[12], account_holder_name),
            (consts.SE_HIL_CON_1_FIELD[13], bank_name),
        ]

        if is_asp:
            hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[8], asp_list))
            hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[9], gzs_list))

        if isinstance(company_info, tuple):
            if is_cdfl:
                hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[14], company_info[2]))
            else:
                hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[10], company_info[2]))

        for key_hil1, cdfl_key, app_type, id_idx, field_idx, is_force, e_write in consts.ROLE_LIST_1:
            if not e_write and not online_sign:
                continue
            key = cdfl_key if is_cdfl else key_hil1
            is_find = False
            if app_type in main_role_info:
                if len(main_role_info[app_type]) >= id_idx+1:
                    is_find = True
                    if isinstance(field_idx, int):
                        hil_contract_1_input.append((key, main_role_info[app_type][id_idx][field_idx]))
                    else:
                        hil_contract_1_input.append((key, field_idx))
            if not is_find and is_force:
                hil_contract_1_input.append((key, empty_str))
        contract_info[consts.HIL_CONTRACT_1_EN] = hil_contract_1_input

        # HIL合同  车辆处置协议 --------------------------------------------------------------------------------------
        if fp_group.find('Joy Select') != -1 or fp_group.find('JoySelect') != -1:
            hil_contract_3_input = [
                (consts.SE_HIL_CON_3_FIELD[0], [full_no] if online_sign else full_no),
                (consts.SE_HIL_CON_3_FIELD[1], main_name),
                (consts.SE_HIL_CON_3_FIELD[2], main_id),
                (consts.SE_HIL_CON_3_FIELD[3], dealer_name),
                (consts.SE_HIL_CON_3_FIELD[4], full_no),
                (consts.SE_HIL_CON_3_FIELD[5], main_name),
                (consts.SE_HIL_CON_3_FIELD[6], main_id),
            ]
            # if online_sign:
            #     hil_contract_3_input.append((consts.SE_HIL_CON_3_FIELD[7], main_name))
            contract_info[consts.HIL_CONTRACT_3_EN] = hil_contract_3_input

        # HIL合同  车辆租赁抵押合同 --------------------------------------------------------------------------------------
        hil_contract_2_input = [
            (consts.SE_HIL_CON_2_FIELD[0], full_no),
            (consts.SE_HIL_CON_2_FIELD[1], full_no),
            (consts.SE_HIL_CON_2_FIELD[2], vin_no),
            (consts.SE_HIL_CON_2_FIELD[3], format(total_amount, '.2f')),
            (consts.SE_HIL_CON_2_FIELD[4], str(cms_info.get('terms', '0'))),
        ]

        for key, app_type_hil2, cdfl_app_type, id_idx, field_idx, is_force, e_write, co_skip in consts.ROLE_LIST_2:
            if co_skip and isinstance(company_info, tuple):
                continue
            if not e_write and not online_sign:
                continue
            app_type = cdfl_app_type if is_cdfl else app_type_hil2
            is_find = False
            if app_type in main_role_info:
                if len(main_role_info[app_type]) >= id_idx+1:
                    is_find = True
                    if isinstance(field_idx, int):
                        hil_contract_2_input.append((key, main_role_info[app_type][id_idx][field_idx]))
                    else:
                        hil_contract_2_input.append((key, field_idx))
            if not is_find and is_force:
                hil_contract_2_input.append((key, empty_str))
        contract_info[consts.HIL_CONTRACT_2_EN] = hil_contract_2_input
        compare_info['contract'] = contract_info
        return compare_info, cms_info.get('autoApprovedDetails', {}).get('aaType', ''), is_gsyh
    else:
        # AFC合同------------------------------------------------------------------------------------------------------
        vehicle_principal_str = str(cms_info.get('financialInformation', {}).get('vehiclePrincipal', '0.0'))
        afc_contract_input = [
            (consts.SE_AFC_CON_FIELD[0], full_no),
            (consts.SE_AFC_CON_FIELD[1], amount),
            (consts.SE_AFC_CON_FIELD[2], vin_no),
            (consts.SE_AFC_CON_FIELD[3], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))),
            (consts.SE_AFC_CON_FIELD[4], str(cms_info.get('terms', '0'))),
            (consts.SE_AFC_CON_FIELD[5], vehicle_principal_str),
            (consts.SE_AFC_CON_FIELD[6], str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.0'))),
            (consts.SE_AFC_CON_FIELD[7], amount),
            (consts.SE_AFC_CON_FIELD[8], vin_no),
            (consts.SE_AFC_CON_FIELD[9], dealer_name),
            (consts.SE_AFC_CON_FIELD[10], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))),
            (consts.SE_AFC_CON_FIELD[11], vehicle_principal_str),
            (consts.SE_AFC_CON_FIELD[12], str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.0'))),
            (consts.SE_AFC_CON_FIELD[13], str(cms_info.get('terms', '0'))),
            (consts.SE_AFC_CON_FIELD[14], account_no),
            (consts.SE_AFC_CON_FIELD[15], account_holder_name),
            (consts.SE_AFC_CON_FIELD[16], bank_name),
            (consts.SE_AFC_CON_FIELD[17], schedule_list_str),
        ]

        if is_asp:
            afc_contract_input.append((consts.SE_AFC_CON_FIELD[20], asp_list))
            afc_contract_input.append((consts.SE_AFC_CON_FIELD[22], asp_list))
            afc_contract_input.append((consts.SE_AFC_CON_FIELD[21], gzs_list))
        else:
            afc_contract_input.pop(5)
            afc_contract_input.pop(5)
            afc_contract_input.pop(9)
            afc_contract_input.pop(9)

        # '借款人签字及时间', 'Borrower', 0, 0, True
        for key_afc1, cdfl_key, app_type, id_idx, field_idx, is_force, e_write in consts.ROLE_LIST:
            if not e_write and not online_sign:
                continue
            key = cdfl_key if is_cdfl else key_afc1
            is_find = False
            if app_type in main_role_info:
                if len(main_role_info[app_type]) >= id_idx+1:
                    is_find = True
                    if isinstance(field_idx, int):
                        afc_contract_input.append((key, main_role_info[app_type][id_idx][field_idx]))
                    else:
                        afc_contract_input.append((key, field_idx))
            if not is_find and is_force:
                afc_contract_input.append((key, empty_str))

        if online_sign:
            afc_contract_input.append((consts.SE_AFC_CON_FIELD[18], consts.SE_STAMP_VALUE))
            afc_contract_input.append((consts.SE_AFC_CON_FIELD[19], empty_str))

        contract_info[consts.AFC_CONTRACT_EN] = afc_contract_input
        compare_info['contract'] = contract_info
        return compare_info, cms_info.get('autoApprovedDetails', {}).get('aaType', ''), is_gsyh


def get_se_cms_compare_info(last_obj, application_entity, detect_list, auto=False):
    cms_info = json.loads(last_obj.content)

    compare_info = {}

    individual_info_dict = {}
    main_role_info = {}
    company_info_list = []

    dealer_name_list = cms_info.get('dealerName', '').split()
    dealer_name = '' if len(dealer_name_list) == 0 else dealer_name_list[-1]

    # 个人信息证件------------------------------------------------------------------------------------------------------
    is_cdfl_bo = False  # 车贷分离,主借
    is_cdfl_co = False  # 车贷分离,共借
    # province = cms_info.get('province', '')
    for individual_info in cms_info.get('applicantInformation', []):
        all_id_num = []

        license_dict = {}

        customer_name = individual_info.get('name', '').strip()
        legal_name = individual_info.get('legalRepName', '')
        establishment_date = individual_info.get('establishmentDate', '')
        # date_of_birth = individual_info.get('dateOfBirth', '')

        # 车贷分离判断
        is_corporate = individual_info.get('customersubType', '') == 'Corporate'
        if individual_info['applicantType'] == consts.APPLICANT_TYPE_ORDER[1] and is_corporate:
            is_cdfl_co = True
        if individual_info['applicantType'] == consts.APPLICANT_TYPE_ORDER[0] and not is_corporate:
            is_cdfl_bo = True

        for id_info in individual_info.get('IDInformation', []):
            if id_info.get('idType') in consts.SE_CMS_FIRST_ID_FIELD_MAPPING:
                license_en, is_prc = consts.SE_CMS_FIRST_ID_FIELD_MAPPING[id_info['idType']]
                # ['customerName', 'idNum', 'dateOfBirth', 'idExpiryDate', 'hukouProvince']
                id_num = decode_des(id_info.get('idNum', ''), des_key)
                field_input = [('customerName', customer_name), ('idNum', id_num),
                               ('idExpiryDate', id_info.get('idExpiryDate', ''))]
                # if is_prc:
                #     field_input.append(('hukouProvince', province))
                #     field_input.append(('真伪', consts.IC_RES_MAPPING.get(1)))
                license_dict[license_en] = field_input
                all_id_num.append(id_num)
            # 营业执照 --------------------------------------------------------------------------------------------------
            elif id_info.get('idType') in ['Unified Social Credit Code', 'Tax Number', 'Business License Number']:
                # ['companyName', 'legalRepName', 'businessLicenseNo', 'organizationCreditCode',
                #  'taxRegistrationCertificateNo', 'establishmentDate', 'businessLicenseDueDate']
                id_num = decode_des(id_info.get('idNum', ''), des_key)
                bl_field_input = [
                    ('companyName', customer_name),
                    ('legalRepName', legal_name),
                    ('businessLicenseNo', id_num),
                    ('organizationCreditCode', id_num),
                    ('taxRegistrationCertificateNo', id_num),
                    ('businessLicenseDueDate', id_info.get('idExpiryDate', '')),
                ]

                if is_corporate:
                    company_info_list.append((customer_name, id_num, legal_name))
                else:
                    bl_field_input.append(('establishmentDate', establishment_date))

                license_dict[consts.BL_EN] = bl_field_input
                all_id_num.append(id_num)

        # SME营业执照---------------------------------------------------------------------------------------------------
        # if individual_info.get('customersubType', '').startswith('Self Employed'):
        #     sep_field_input = [
        #         ('legalRepName', customer_name),
        #         ('businessLicenseDueDate', ''),
        #     ]
        #     license_dict[consts.SME_BL_EN] = sep_field_input

        if len(all_id_num) > 0:
            main_role_info.setdefault(individual_info['applicantType'], []).append(
                (customer_name, '、'.join(all_id_num), all_id_num[0])
            )

        if len(license_dict) > 0:
            individual_info_dict.setdefault(individual_info['applicantType'], []).append(license_dict)

    compare_info['applicantInformation'] = individual_info_dict

    main_name = main_id_all = main_id = ''
    for applicant_type in consts.APPLICANT_TYPE_ORDER:
        if applicant_type in main_role_info:
            main_name, main_id_all, main_id = main_role_info[applicant_type][0]
            # hmh_name, _, hmh_id = main_role_info[applicant_type][0]
            break

    co_name = co_id = bo_name = bo_id = ''
    is_cdfl = is_cdfl_bo and is_cdfl_co
    if is_cdfl:
        if len(main_role_info.get(consts.APPLICANT_TYPE_ORDER[1], [])) > 0:
            co_name, _, co_id = main_role_info[consts.APPLICANT_TYPE_ORDER[1]][0]
        else:
            co_name = co_id = ''
        if len(main_role_info.get(consts.APPLICANT_TYPE_ORDER[0], [])) > 0:
            bo_name, _, bo_id = main_role_info[consts.APPLICANT_TYPE_ORDER[0]][0]
        else:
            bo_name = bo_id = ''

    # dda_name_list = []
    # dda_num_list = []
    if len(company_info_list) > 0:
        # tmp_idx = 1
        company_info = company_info_list[0]
    else:
        # tmp_idx = 0
        company_info = None

    # for applicant_type in consts.APPLICANT_TYPE_ORDER[tmp_idx: tmp_idx + 2]:
    #     if applicant_type in main_role_info:
    #         for dda_name_part, _, dda_num_part in main_role_info[applicant_type]:
    #             dda_name_list.append(dda_name_part)
    #             dda_num_list.append(dda_num_part)
    # dda_name = '、'.join(dda_name_list)
    # dda_num = '、'.join(dda_num_list)
    # del main_role_info

    vehicle_info = {}
    vehicle_field_input = []
    vehicle_status = cms_info.get('vehicleStatus', '')
    first_submission_date = cms_info.get('submissionDate', '')
    vin_no = cms_info.get('vehicleInformation', {}).get('vinNo', '')
    amount = str(cms_info.get('financialInformation', {}).get('vehiclePrice', '0.0'))
    # 新车发票----------------------------------------------------------------------------------------------------------
    if vehicle_status == 'New':
        vehicle_field_input.append(('vinNo', vin_no))
        vehicle_field_input.append(('dealer', '、'.join([dealer_name, cms_info.get('fapiaoIssuerDealer', '')])))
        vehicle_field_input.append(('vehicleTransactionAmount', amount))

        if isinstance(company_info, tuple):
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0]))  # 车贷分离
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1]))  # 车贷分离
        else:
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name))  # 车贷分离
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id))  # 车贷分离
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[2], first_submission_date))
        # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[3], consts.SE_STAMP_VALUE))
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[4], consts.SE_FPL_VALUE))
        bhsj = float(amount) / 1.13
        # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[5], consts.SPLIT_STR.join([
        #     format(bhsj, '.2f'),
        #     format(float(amount) - bhsj, '.2f'),
        #     consts.RESULT_Y
        # ])))
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[7], format(bhsj, '.2f')))
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[8], format(float(amount) - bhsj, '.2f')))
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[9], consts.RESULT_Y))
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[6], consts.SE_LAYOUT_VALUE))
        vehicle_info[consts.MVI_EN] = vehicle_field_input
    # 二手车发票、交易凭证、绿本------------------------------------------------------------------------------------------
    else:
        gb_field_input = [
            ('vinNo', vin_no),
        ]
        gb34_field_input = []
        jypz_field_input = []
        vehicle_field_input.append(('vinNo', vin_no))
        vehicle_field_input.append(('vehicleTransactionAmount', amount))
        if isinstance(company_info, tuple):
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0]))  # 车贷分离
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1]))  # 车贷分离
            jypz_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0]))  # 车贷分离
            jypz_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1]))  # 车贷分离
            gb34_field_input.append((consts.SE_GB_USED_FIELD[0], co_name if is_cdfl else company_info[0]))  # 车贷分离
            gb34_field_input.append((consts.SE_GB_USED_FIELD[1], co_id if is_cdfl else company_info[1]))  # 车贷分离
        else:
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name))  # 车贷分离
            vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id_all))  # 车贷分离
            jypz_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name))  # 车贷分离
            jypz_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id_all))  # 车贷分离
            gb34_field_input.append((consts.SE_GB_USED_FIELD[0], co_name if is_cdfl else main_name))  # 车贷分离
            gb34_field_input.append((consts.SE_GB_USED_FIELD[1], co_id if is_cdfl else main_id_all))  # 车贷分离
        gb34_field_input.append((consts.SE_GB_USED_FIELD[2], first_submission_date))
        vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[2], first_submission_date))
        # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[3], consts.SE_STAMP_VALUE))
        jypz_field_input.append(('dealerName', dealer_name))
        jypz_field_input.append(('vinNo', vin_no))
        jypz_field_input.append(('vehicleTransactionAmount', amount))
        jypz_field_input.append((consts.SE_GB_USED_FIELD[-1], first_submission_date))

        vehicle_info[consts.MVC_EN] = gb_field_input
        vehicle_info[consts.MVC34_EN] = gb34_field_input
        if not detect_list[0]:
            vehicle_info[consts.UCI_EN] = vehicle_field_input
        if not detect_list[1]:
            vehicle_info[consts.JYPZ_EN] = jypz_field_input
        if detect_list[0] and detect_list[1]:
            vehicle_info[consts.UCI_EN] = vehicle_field_input
    compare_info['vehicleInfo'] = vehicle_info

    # 银行卡-------------------------------------------------------------------------------------------------------
    bank_info = {}
    bank_name = cms_info.get('bankAccountDetails', {}).get('bankName', '')
    account_no = decode_des(cms_info.get('bankAccountDetails', {}).get('accountNo', ''), des_key)
    account_holder_name = cms_info.get('bankAccountDetails', {}).get('accountHolderName', '')
    is_gsyh = True if '工商' in bank_name else False

    if isinstance(company_info, tuple) and company_info[0] == account_holder_name:
        pass
    else:
        bank_field_input = [
            ('accountNo', account_no),
            ('bankName', bank_name),
            ('type', consts.BC_TYPE_VALUE),
        ]
        bank_info[consts.BC_EN] = bank_field_input

    # DDA------------------------------------------------------------------------------------------------------------
    # if is_gsyh or not detect_list[-1]:
    #     dda_field_input = [
    #         ('applicationId(1)', last_obj.application_id),
    #         ('applicationId(2)', last_obj.application_id),
    #         ('bankName', bank_name),
    #         ('companyName', consts.HIL_COMPANY_NAME if application_entity in consts.HIL_SET else consts.AFC_COMPANY_NAME),
    #         ('customerName', dda_name),
    #         ('idNum', dda_num),
    #         ('accountHolderName', account_holder_name),
    #         ('accountNo', account_no),
    #     ]
    #     bank_info[consts.DDA_EN] = dda_field_input
    if len(bank_info) > 0:
        compare_info['bankInfo'] = bank_info

    # 银行流水 --------------------------------------------------------------------
    if cms_info.get('autoApprovedDetails', {}).get('aaType', '') in ['CAA1', 'CAA2'] and \
            cms_info.get('autoApprovedDetails', {}).get('PolicyComments', '') != '此申请无需提供流水':
        date_timedelta = 60 if auto else 90
        bs_role_list = []
        for applicant_type in consts.APPLICANT_TYPE_ORDER[:2]:
            if applicant_type in main_role_info:
                for bs_role, _, _ in main_role_info[applicant_type]:
                    bs_role_list.append(bs_role)

        bs_info = dict()
        bs_field_input = [
            (consts.SE_BS_FIELD[0], bs_role_list),
            (consts.SE_BS_FIELD[1], first_submission_date),
            (consts.SE_BS_FIELD[2], date_timedelta),
        ]

        dbr_bs_role_list = []
        for dbr_bs_role, _, _ in main_role_info.get(consts.APPLICANT_TYPE_ORDER[2], []):
            dbr_bs_role_list.append(dbr_bs_role)

        if len(dbr_bs_role_list) >= 1:
            bs_field_input.extend([
                (consts.SE_BS_FIELD[3], dbr_bs_role_list[0]),
                (consts.SE_BS_FIELD[4], first_submission_date),
                (consts.SE_BS_FIELD[5], date_timedelta),
            ])
            if len(dbr_bs_role_list) >= 2:
                bs_field_input.extend([
                    (consts.SE_BS_FIELD[6], dbr_bs_role_list[1]),
                    (consts.SE_BS_FIELD[7], first_submission_date),
                    (consts.SE_BS_FIELD[8], date_timedelta),
                ])
        bs_info[consts.BS_EN] = bs_field_input
        compare_info['Bank Statement'] = bs_info

    # 抵押登记豁免函----------------------------------------------------------------------------------------------------
    other_info = {}
    full_no = cms_info.get('settlemnetVerification', {}).get('applicationNo', '')
    if cms_info.get('mortgageType', '') == 'Mortgage Free' or cms_info.get('mortgageType', '') == 'MortgageFree':
        hmh_field_input = [
            (consts.SE_HMH_FIELD[0], main_name),
            (consts.SE_HMH_FIELD[1], main_id),
            (consts.SE_HMH_FIELD[2], full_no),
            (consts.SE_HMH_FIELD[3], cms_info.get('financeCompany', '')),
            (consts.SE_HMH_FIELD[4], consts.SE_STAMP_VALUE),
        ]
        other_info[consts.HMH_EN] = hmh_field_input

    # ASP -------------------------------------------------------------------------------------------------------
    asp_list = []
    gzs_status = consts.GZS_STATUS[1]
    gzs_list = [gzs_status]
    gzs_price = '0.00'
    is_asp = False
    insurance_price = None
    if str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.00')) != '0.00':
        is_asp = True
        # for asp_info in cms_info.get('associatedServices', []):
        for asp_info in cms_info.get('associatedServices', {}).get('SubassociatedServices', []):
            tmp_asp_name = asp_info.get('associatedServices')
            if isinstance(tmp_asp_name, str) and len(tmp_asp_name) > 0:
                if gzs_status == consts.GZS_STATUS[1] and tmp_asp_name.find(consts.GZS_NAME) != -1:
                    gzs_status = consts.GZS_STATUS[2]
                    gzs_price = asp_info.get('price', '0.00')
                asp_list.append(
                    (
                        tmp_asp_name,
                        asp_info.get('price', '0.00'),
                        asp_info.get('financed', '0.00')
                    )
                )
                # 保单费合计
                if tmp_asp_name.find('机动车辆保险') != -1:
                    insurance_price = asp_info.get('price', '0.00')

        fin_total = 0
        # fin_total_tmp = cms_info.get('associatedServices', {}).get('financed total', '0.00')
        # fin_total = '0.00' if fin_total_tmp.strip() == '' else fin_total_tmp
        for asp_name, _, asp_fin in asp_list:
            if gzs_status == consts.GZS_STATUS[2] and asp_name.find(consts.GZS_NAME) == -1:
                gzs_status = consts.GZS_STATUS[0]
            fin_total += float(asp_fin)
        asp_list.append(
            (
                consts.ASP_SUM_NAME,
                '',
                # fin_total,
                format(fin_total, '.2f'),
            )
        )

        # CMS Vehicle Price / 1.13 * 10 %
        gzs_list = [gzs_status]
        if gzs_status != consts.GZS_STATUS[1]:
            gzs_value = float(amount) * 0.1 / 1.13
            gzs_list.append(gzs_value)
            gzs_list.append(float(gzs_price))

    # 保单 -----------------------------------------------------------------------------------------------------------
    is_insurance = 0
    fp_campaign = cms_info.get('fpCampaign', '')
    fp_group = cms_info.get('fpGroup', '')
    insurance_type = cms_info.get('insuranceDetails', {}).get('insuranceType', '')
    if insurance_type == 'Waive Insurance' and isinstance(insurance_price, str):
        is_insurance = 1
    elif insurance_type == 'Comprehensive Insurance':
        is_insurance = 2
    if is_insurance != 0:
        if fp_campaign.find('OCU') == -1:
            ssx_amount = amount
        else:
            ssx_amount = format(float(amount) * 0.8, '.2f')
        if fp_campaign.find('Joy_Plus') == -1 or fp_campaign.find('JoyPlus') == -1:
            dszx_amount = '200000'
        else:
            dszx_amount = '500000'
        bd_field_input = [
            (consts.SE_BD_FIELD[0], [co_name, bo_name] if is_cdfl else [main_name, ]),  # 车贷分离
            (consts.SE_BD_FIELD[1], [co_id, bo_id] if is_cdfl else [main_id, ]),  # 车贷分离
            (consts.SE_BD_FIELD[2], vin_no),
            (consts.SE_BD_FIELD[3], ssx_amount),
            (consts.SE_BD_FIELD[4], dszx_amount),
            (consts.SE_BD_FIELD[5], consts.JDMPV_VALUE),
            (consts.SE_BD_FIELD[6], cms_info.get('insuranceDetails', {}).get('startDate', '')),
            (consts.SE_BD_FIELD[7], cms_info.get('insuranceDetails', {}).get('endDate', '')),
            (consts.SE_BD_FIELD[8], consts.SE_STAMP_VALUE),
            (consts.SE_BD_FIELD[9], consts.SE_DYSYR_VALUE),
        ]
        if is_insurance == 1:
            bd_field_input.append((consts.SE_BD_FIELD[10], insurance_price))
        other_info[consts.BD_EN] = bd_field_input

    if len(other_info) > 0:
        compare_info['other'] = other_info

    schedule_list = []
    total_amount = 0
    for schedule_dict in cms_info.get('paymentSchedule', []):
        tmp_str = "{1}{0}{2}".format(consts.SPLIT_STR, str(schedule_dict.get('no', '')),
                                     str(schedule_dict.get('grossRentalAmount', '')))
        schedule_list.append(tmp_str)
        total_amount += float(schedule_dict.get('grossRentalAmount', '0.0'))
    schedule_list_str = consts.SCHEDULE_SPLIT_STR.join(schedule_list)

    online_sign = cms_info.get('contractSource', 'Online Sign') == 'Online Sign'

    contract_info = {}
    if application_entity in consts.HIL_SET:
        # HIL合同  售后回租合同 --------------------------------------------------------------------------------------
        hil_contract_1_input = [
            (consts.SE_HIL_CON_1_FIELD[0], [full_no] if online_sign else full_no),
            (consts.SE_HIL_CON_1_FIELD[1], full_no),
            (consts.SE_HIL_CON_1_FIELD[2], vin_no),
            (consts.SE_HIL_CON_1_FIELD[3], dealer_name),
            (consts.SE_HIL_CON_1_FIELD[4], amount),
            (consts.SE_HIL_CON_1_FIELD[5], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))),
            (consts.SE_HIL_CON_1_FIELD[6], str(cms_info.get('terms', '0'))),
            (consts.SE_HIL_CON_1_FIELD[7], schedule_list_str),
            (consts.SE_HIL_CON_1_FIELD[11], account_no),
            (consts.SE_HIL_CON_1_FIELD[12], account_holder_name),
            (consts.SE_HIL_CON_1_FIELD[13], bank_name),
        ]

        if is_asp:
            hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[8], asp_list))
            hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[9], gzs_list))

        if isinstance(company_info, tuple):
            if is_cdfl:
                hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[14], company_info[2]))
            else:
                hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[10], company_info[2]))

        for key_hil1, cdfl_key, app_type, id_idx, field_idx, is_force, e_write in consts.ROLE_LIST_1:
            if not e_write and not online_sign:
                continue
            key = cdfl_key if is_cdfl else key_hil1
            is_find = False
            if app_type in main_role_info:
                if len(main_role_info[app_type]) >= id_idx+1:
                    is_find = True
                    if isinstance(field_idx, int):
                        hil_contract_1_input.append((key, main_role_info[app_type][id_idx][field_idx]))
                    else:
                        hil_contract_1_input.append((key, field_idx))
            if not is_find and is_force:
                hil_contract_1_input.append((key, empty_str))
        contract_info[consts.HIL_CONTRACT_1_EN] = hil_contract_1_input

        # HIL合同  车辆处置协议 --------------------------------------------------------------------------------------
        if fp_group.find('Joy Select') != -1 or fp_group.find('JoySelect') != -1:
            hil_contract_3_input = [
                (consts.SE_HIL_CON_3_FIELD[0], [full_no] if online_sign else full_no),
                (consts.SE_HIL_CON_3_FIELD[1], main_name),
                (consts.SE_HIL_CON_3_FIELD[2], main_id),
                (consts.SE_HIL_CON_3_FIELD[3], dealer_name),
                (consts.SE_HIL_CON_3_FIELD[4], full_no),
                (consts.SE_HIL_CON_3_FIELD[5], main_name),
                (consts.SE_HIL_CON_3_FIELD[6], main_id),
            ]
            if online_sign:
                hil_contract_3_input.append((consts.SE_HIL_CON_3_FIELD[7], main_name))
            contract_info[consts.HIL_CONTRACT_3_EN] = hil_contract_3_input

        # HIL合同  车辆租赁抵押合同 --------------------------------------------------------------------------------------
        hil_contract_2_input = [
            (consts.SE_HIL_CON_2_FIELD[0], full_no),
            (consts.SE_HIL_CON_2_FIELD[1], full_no),
            (consts.SE_HIL_CON_2_FIELD[2], vin_no),
            (consts.SE_HIL_CON_2_FIELD[3], format(total_amount, '.2f')),
            (consts.SE_HIL_CON_2_FIELD[4], str(cms_info.get('terms', '0'))),
        ]

        for key, app_type_hil2, cdfl_app_type, id_idx, field_idx, is_force, e_write, co_skip in consts.ROLE_LIST_2:
            if co_skip and isinstance(company_info, tuple):
                continue
            if not e_write and not online_sign:
                continue
            app_type = cdfl_app_type if is_cdfl else app_type_hil2
            is_find = False
            if app_type in main_role_info:
                if len(main_role_info[app_type]) >= id_idx+1:
                    is_find = True
                    if isinstance(field_idx, int):
                        hil_contract_2_input.append((key, main_role_info[app_type][id_idx][field_idx]))
                    else:
                        hil_contract_2_input.append((key, field_idx))
            if not is_find and is_force:
                hil_contract_2_input.append((key, empty_str))
        contract_info[consts.HIL_CONTRACT_2_EN] = hil_contract_2_input
        compare_info['contract'] = contract_info
        return compare_info, cms_info.get('applicationVersion', 1), is_gsyh
    else:
        # AFC合同------------------------------------------------------------------------------------------------------
        vehicle_principal_str = str(cms_info.get('financialInformation', {}).get('vehiclePrincipal', '0.0'))
        afc_contract_input = [
            (consts.SE_AFC_CON_FIELD[0], full_no),
            (consts.SE_AFC_CON_FIELD[1], amount),
            (consts.SE_AFC_CON_FIELD[2], vin_no),
            (consts.SE_AFC_CON_FIELD[3], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))),
            (consts.SE_AFC_CON_FIELD[4], str(cms_info.get('terms', '0'))),
            (consts.SE_AFC_CON_FIELD[5], vehicle_principal_str),
            (consts.SE_AFC_CON_FIELD[6], str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.0'))),
            (consts.SE_AFC_CON_FIELD[7], amount),
            (consts.SE_AFC_CON_FIELD[8], vin_no),
            (consts.SE_AFC_CON_FIELD[9], dealer_name),
            (consts.SE_AFC_CON_FIELD[10], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))),
            (consts.SE_AFC_CON_FIELD[11], vehicle_principal_str),
            (consts.SE_AFC_CON_FIELD[12], str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.0'))),
            (consts.SE_AFC_CON_FIELD[13], str(cms_info.get('terms', '0'))),
            (consts.SE_AFC_CON_FIELD[14], account_no),
            (consts.SE_AFC_CON_FIELD[15], account_holder_name),
            (consts.SE_AFC_CON_FIELD[16], bank_name),
            (consts.SE_AFC_CON_FIELD[17], schedule_list_str),
        ]

        if is_asp:
            afc_contract_input.append((consts.SE_AFC_CON_FIELD[20], asp_list))
            afc_contract_input.append((consts.SE_AFC_CON_FIELD[22], asp_list))
            afc_contract_input.append((consts.SE_AFC_CON_FIELD[21], gzs_list))
        else:
            afc_contract_input.pop(5)
            afc_contract_input.pop(5)
            afc_contract_input.pop(9)
            afc_contract_input.pop(9)

        # '借款人签字及时间', 'Borrower', 0, 0, True
        for key_afc1, cdfl_key, app_type, id_idx, field_idx, is_force, e_write in consts.ROLE_LIST:
            if not e_write and not online_sign:
                continue
            key = cdfl_key if is_cdfl else key_afc1
            is_find = False
            if app_type in main_role_info:
                if len(main_role_info[app_type]) >= id_idx+1:
                    is_find = True
                    if isinstance(field_idx, int):
                        afc_contract_input.append((key, main_role_info[app_type][id_idx][field_idx]))
                    else:
                        afc_contract_input.append((key, field_idx))
            if not is_find and is_force:
                afc_contract_input.append((key, empty_str))

        if online_sign:
            afc_contract_input.append((consts.SE_AFC_CON_FIELD[18], consts.SE_STAMP_VALUE))
            afc_contract_input.append((consts.SE_AFC_CON_FIELD[19], empty_str))

        contract_info[consts.AFC_CONTRACT_EN] = afc_contract_input
        compare_info['contract'] = contract_info
        return compare_info, cms_info.get('applicationVersion', 1), is_gsyh


def se_bs_compare(license_en, ocr_res_dict, strip_list, is_auto):
    # 主共借至少提供一个
    # 有担保人,担保人必须提供。主共借没有时,修改comment:人工查看担保人亲属关系

    if is_auto:
        ocr_field, compare_logic, _ = consts.SE_COMPARE_FIELD_AUTO[license_en]
    else:
        ocr_field, compare_logic, _ = consts.SE_COMPARE_FIELD[license_en]
    ocr_res_str = ocr_res_dict.get(ocr_field)

    result_field_list = []
    field_img_path_dict = dict()

    if ocr_res_str is not None:
        pre_field_list = strip_list[:3]
        dbr1_field_list = strip_list[3:6]
        dbr2_field_list = strip_list[6:]

        ocr_res_list = json.loads(ocr_res_str)
        # length = len(ocr_res_list)

        # 主共借人
        pre_best_res = {}
        max_correct_count = 0
        for ocr_res in ocr_res_list:
            correct_count = 0
            pre_tmp_res_part = {}
            for idx, (name, value) in enumerate(pre_field_list):
                ocr_str_or_list = ocr_res.get(compare_logic[name][0])
                if isinstance(ocr_str_or_list, str) or isinstance(ocr_str_or_list, list) \
                        or isinstance(ocr_str_or_list, int):
                    result = getattr(cp, compare_logic[name][1])(value, ocr_str_or_list, **compare_logic[name][2])
                    if isinstance(ocr_str_or_list, list):
                        ocr_str = json.dumps(ocr_str_or_list, ensure_ascii=False)
                    else:
                        ocr_str = ocr_str_or_list
                    reason = compare_logic[name][3]
                else:
                    result = consts.RESULT_N
                    ocr_str = empty_str
                    reason = compare_logic[name][3]

                if idx == 0 and result == consts.RESULT_N:
                    break

                if result == consts.RESULT_Y:
                    correct_count += 1
                pre_tmp_res_part[name] = (result, ocr_str, reason)

            if correct_count > 0 and correct_count >= max_correct_count:
                max_correct_count = correct_count
                pre_best_res = pre_tmp_res_part

        # 担保人1
        dbr1_best_res = {}
        if len(dbr1_field_list) > 0:
            max_correct_count = 0
            for ocr_res in ocr_res_list:
                correct_count = 0
                dbr1_tmp_res_part = {}
                for idx, (name, value) in enumerate(dbr1_field_list):
                    ocr_str_or_list = ocr_res.get(compare_logic[name][0])
                    if isinstance(ocr_str_or_list, str) or isinstance(ocr_str_or_list, list) or isinstance(ocr_str_or_list, int):
                        result = getattr(cp, compare_logic[name][1])(value, ocr_str_or_list, **compare_logic[name][2])
                        if isinstance(ocr_str_or_list, list):
                            ocr_str = json.dumps(ocr_str_or_list, ensure_ascii=False)
                        else:
                            ocr_str = ocr_str_or_list
                        reason = compare_logic[name][3]
                    else:
                        result = consts.RESULT_N
                        ocr_str = empty_str
                        reason = compare_logic[name][3]

                    if idx == 0 and result == consts.RESULT_N:
                        break

                    if result == consts.RESULT_Y:
                        correct_count += 1
                    dbr1_tmp_res_part[name] = (result, ocr_str, reason)

                if correct_count > 0 and correct_count >= max_correct_count:
                    max_correct_count = correct_count
                    dbr1_best_res = dbr1_tmp_res_part

        # 担保人2
        dbr2_best_res = {}
        if len(dbr1_field_list) > 0:
            max_correct_count = 0
            for ocr_res in ocr_res_list:
                correct_count = 0
                dbr2_tmp_res_part = {}
                for idx, (name, value) in enumerate(dbr2_field_list):
                    ocr_str_or_list = ocr_res.get(compare_logic[name][0])
                    if isinstance(ocr_str_or_list, str) or isinstance(ocr_str_or_list, list) or isinstance(ocr_str_or_list, int):
                        result = getattr(cp, compare_logic[name][1])(value, ocr_str_or_list, **compare_logic[name][2])
                        if isinstance(ocr_str_or_list, list):
                            ocr_str = json.dumps(ocr_str_or_list, ensure_ascii=False)
                        else:
                            ocr_str = ocr_str_or_list
                        reason = compare_logic[name][3]
                    else:
                        result = consts.RESULT_N
                        ocr_str = empty_str
                        reason = compare_logic[name][3]

                    if idx == 0 and result == consts.RESULT_N:
                        break

                    if result == consts.RESULT_Y:
                        correct_count += 1
                    dbr2_tmp_res_part[name] = (result, ocr_str, reason)

                if correct_count > 0 and correct_count >= max_correct_count:
                    max_correct_count = correct_count
                    dbr2_best_res = dbr2_tmp_res_part

        dbr_ok = False
        # 有担保人
        if len(dbr1_field_list) > 0:
            # 有担保人12
            if len(dbr2_field_list) > 0:
                if len(dbr1_best_res) > 0 and len(dbr2_best_res) > 0:
                    dbr_ok = True
            # 有担保人1
            else:
                if len(dbr1_best_res) > 0:
                    dbr_ok = True
        # 无担保人
        # else:
        #     pass

        best_res_empty = False
        if len(pre_best_res) == 0 and len(dbr1_best_res) == 0 and len(dbr2_best_res) == 0:
            best_res_empty = True

        for name, value in pre_field_list:
            if len(pre_best_res) > 0:
                result, ocr_str, reason = pre_best_res[name]
            else:
                result = consts.RESULT_N
                ocr_str = empty_str
                if best_res_empty:
                    reason = consts.SPECIAL_REASON_3
                elif dbr_ok:  # 有担保人且担保人都提供了流水
                    reason = consts.SPECIAL_REASON
                else:
                    reason = compare_logic[pre_field_list[0][0]][3]
            img_path = empty_str
            error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value
            if isinstance(value, list):
                value = json.dumps(value, ensure_ascii=False)
            result_field_list.append((name, value, result, ocr_str, img_path, error_type, reason))

        if len(dbr1_field_list) > 0:
            for name, value in dbr1_field_list:
                if len(dbr1_best_res) > 0:
                    result, ocr_str, reason = dbr1_best_res[name]
                else:
                    result = consts.RESULT_N
                    ocr_str = empty_str
                    if best_res_empty:
                        reason = consts.SPECIAL_REASON_3
                    elif len(pre_best_res) > 0:
                        reason = consts.SPECIAL_REASON_2
                    else:
                        reason = compare_logic[dbr1_field_list[0][0]][3]
                img_path = empty_str
                error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value
                if isinstance(value, list):
                    value = json.dumps(value, ensure_ascii=False)
                result_field_list.append((name, value, result, ocr_str, img_path, error_type, reason))

        if len(dbr2_field_list) > 0:
            for name, value in dbr2_field_list:
                if len(dbr2_best_res) > 0:
                    result, ocr_str, reason = dbr2_best_res[name]
                else:
                    result = consts.RESULT_N
                    ocr_str = empty_str
                    if best_res_empty:
                        reason = consts.SPECIAL_REASON_3
                    elif len(pre_best_res) > 0:
                        reason = consts.SPECIAL_REASON_2
                    else:
                        reason = compare_logic[dbr2_field_list[0][0]][3]
                img_path = empty_str
                error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value
                if isinstance(value, list):
                    value = json.dumps(value, ensure_ascii=False)
                result_field_list.append((name, value, result, ocr_str, img_path, error_type, reason))

    else:
        for name, value in strip_list:
            if isinstance(value, list):
                value = json.dumps(value, ensure_ascii=False)
            result_field_list.append((name, value, consts.RESULT_N, empty_str, empty_str, ErrorType.NF.value,
                                      consts.SPECIAL_REASON_3))

    return result_field_list, field_img_path_dict


def se_compare_license(license_en, ocr_res_dict, field_list):
    ocr_field, compare_logic, special_expiry_date = consts.SE_COMPARE_FIELD[license_en]

    is_find = False
    no_ocr_result = False
    special_expiry_date_slice = False
    result_field_list = []
    section_img_info = dict()
    field_img_path_dict = dict()
    ocr_res_str = ocr_res_dict.get(ocr_field)
    if ocr_res_str is not None:
        ocr_res_list = json.loads(ocr_res_str)

        # 3/4页去除
        if ocr_field == consts.MVC_OCR_FIELD:
            tmp_list = []
            for res in ocr_res_list:
                if compare_logic['vinNo'][0] in res:
                    tmp_list.append(res)
            ocr_res_list = tmp_list

        length = len(ocr_res_list)

        # 身份证、居住证 过期期限特殊处理
        if special_expiry_date:
            expiry_dates = dict()
            key = compare_logic.get('idExpiryDate')[0]
            for date_tmp_idx, ocr_res in enumerate(ocr_res_list):
                if key in ocr_res:
                    expiry_dates[ocr_res[key]] = (ocr_res.get(consts.IMG_PATH_KEY_2, ''), date_tmp_idx)
        else:
            expiry_dates = dict()

        for res_idx in range(length-1, -1, -1):
            if is_find:
                break

            for idx, (name, value) in enumerate(field_list):
                if ocr_field == consts.MVI_OCR_FIELD and name == consts.SE_NEW_ADD_FIELD[9]:
                    ocr_str = getattr(cp, consts.ZW_METHOD)(
                        ocr_res_list[res_idx].get(consts.LOWER_AMOUNT_FIELD, ''),
                        ocr_res_list[res_idx].get(consts.UPPER_AMOUNT_FIELD, ''),
                    )
                else:
                    ocr_str = ocr_res_list[res_idx].get(compare_logic[name][0])
                if not isinstance(ocr_str, str):
                    result = consts.RESULT_N
                    ocr_str = empty_str
                    no_key = True
                else:
                    result = getattr(cp, compare_logic[name][1])(value, ocr_str, **compare_logic[name][2])
                    no_key = False

                if idx == 0 and result == consts.RESULT_N and length > 1:
                    break

                is_find = True
                section_img_info[consts.SECTION_IMG_PATH_KEY] = ocr_res_list[res_idx].get(consts.SECTION_IMG_PATH_KEY, '')
                section_img_info[consts.ALL_POSITION_KEY] = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY, {})
                if special_expiry_date:
                    section_img_info[consts.SECTION_IMG_PATH_KEY_2] = ocr_res_list[res_idx].get(
                        consts.SECTION_IMG_PATH_KEY_2, '')
                    section_img_info[consts.ALL_POSITION_KEY_2] = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY_2, {})

                # 过期期限特殊处理
                if special_expiry_date and name == 'idExpiryDate' and result == consts.RESULT_N:
                    if no_key:
                        for expiry_date, (date_img_path, date_res_idx) in expiry_dates.items():
                            expiry_date_res = getattr(cp, compare_logic[name][1])(value, expiry_date, **compare_logic[name][2])
                            if expiry_date_res == consts.RESULT_N:
                                ocr_str = expiry_date
                                img_path = date_img_path
                                special_expiry_date_slice = True
                                section_img_info[consts.SECTION_IMG_PATH_KEY_2] = ocr_res_list[date_res_idx].get(
                                    consts.SECTION_IMG_PATH_KEY_2, '')
                                section_img_info[consts.ALL_POSITION_KEY_2] = ocr_res_list[date_res_idx].get(
                                    consts.ALL_POSITION_KEY_2, {})
                                break
                        else:
                            ocr_str = empty_str
                            result = consts.RESULT_Y
                            img_path = empty_str
                    else:
                        img_path = ocr_res_list[res_idx].get(consts.IMG_PATH_KEY_2, '')
                        special_expiry_date_slice = True
                else:
                    img_path = ocr_res_list[res_idx].get(consts.IMG_PATH_KEY, '') if result == consts.RESULT_N else empty_str
                if isinstance(value, list):
                    value = json.dumps(value, ensure_ascii=False)
                error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value
                result_field_list.append((name, value, result, ocr_str, img_path, error_type, compare_logic[name][3]))
    else:
        no_ocr_result = True

    if not is_find:
        for name, value in field_list:
            if isinstance(value, list):
                value = json.dumps(value, ensure_ascii=False)
            no_find_str = consts.DDA_NO_FIND if license_en == consts.DDA_EN else '{0}未找到'.format(license_en)
            result_field_list.append((name, value, consts.RESULT_N, empty_str, empty_str, ErrorType.NF.value, no_find_str))

    if is_find:
        if special_expiry_date_slice:
            special_section_img_path = section_img_info.get(consts.SECTION_IMG_PATH_KEY_2, '')
            if os.path.exists(special_section_img_path):
                field = 'idExpiryDate'
                special_info = section_img_info.get(consts.ALL_POSITION_KEY_2, {})
                special_section_position = special_info.get(consts.POSITION_KEY, {})
                special_section_angle = special_info.get(consts.ANGLE_KEY, 0)
                try:
                    last_img = img_process(special_section_img_path, special_section_position, special_section_angle)
                except Exception as e:
                    field_img_path_dict[field] = special_section_img_path
                else:
                    pre, suf = os.path.splitext(special_section_img_path)
                    try:
                        res_field = compare_logic[field][0]
                        is_valid, coord_tuple = field_build_coordinates(special_info.get(res_field, {}))
                        if is_valid:
                            save_path = '{0}_{1}{2}'.format(pre, field, suf)
                            field_img = last_img[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :]
                            cv2.imwrite(save_path, field_img)
                            field_img_path_dict[field] = save_path
                        else:
                            field_img_path_dict[field] = special_section_img_path
                    except Exception as e:
                        field_img_path_dict[field] = special_section_img_path

        section_img_path = section_img_info.get(consts.SECTION_IMG_PATH_KEY, '')
        if os.path.exists(section_img_path):
            failed_field = []
            base_img_path = empty_str
            for name, _, result, _, img_path, _, _ in result_field_list:
                if result == consts.RESULT_N:
                    if special_expiry_date_slice and name == 'idExpiryDate':
                        continue
                    failed_field.append(name)
                    if base_img_path == empty_str:
                        base_img_path = img_path
            if len(failed_field) > 0:
                info = section_img_info.get(consts.ALL_POSITION_KEY, {})
                section_position = info.get(consts.POSITION_KEY, {})
                section_angle = info.get(consts.ANGLE_KEY, 0)
                try:
                    last_img = img_process(section_img_path, section_position, section_angle)
                except Exception as e:
                    for field in failed_field:
                        field_img_path_dict[field] = base_img_path
                else:
                    pre, suf = os.path.splitext(section_img_path)
                    for field in failed_field:
                        try:
                            res_field = compare_logic[field][0]
                            is_valid, coord_tuple = field_build_coordinates(info.get(res_field, {}))
                            if is_valid:
                                save_path = '{0}_{1}{2}'.format(pre, field, suf)
                                field_img = last_img[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :]
                                cv2.imwrite(save_path, field_img)
                                field_img_path_dict[field] = save_path
                            else:
                                field_img_path_dict[field] = base_img_path
                        except Exception as e:
                            field_img_path_dict[field] = base_img_path

    return result_field_list, no_ocr_result, field_img_path_dict


def se_contract_compare(license_en, ocr_res_dict, strip_list, is_gsyh):
    ocr_field, compare_logic, _ = consts.SE_COMPARE_FIELD[license_en]
    ocr_res_str = ocr_res_dict.get(ocr_field)

    result_field_list = []
    field_img_path_dict = dict()

    ocr_res = dict()
    if ocr_res_str is not None:
        ocr_res_list = json.loads(ocr_res_str)
        ocr_res = ocr_res_list.pop()

        for name, value in strip_list:
            # 购置税校验
            if name == consts.SE_AFC_CON_FIELD[21]:
                if len(value) == 3:
                    reason = []
                    gzs_verify = value[1] >= value[2]
                    if gzs_verify:
                        if value[0] == consts.GZS_STATUS[0]:
                            reason.append(consts.GZS_REASON_1)
                            result = consts.RESULT_N
                        else:
                            result = consts.RESULT_Y
                    else:
                        if value[0] == consts.GZS_STATUS[0]:
                            reason.append(consts.GZS_REASON_1)
                        result = consts.RESULT_N
                        reason.append(consts.GZS_REASON_2)
                else:
                    result = consts.RESULT_N
                    reason = consts.GZS_REASON_1
                ocr_str = empty_str
            else:
                ocr_str_or_list = ocr_res.get(compare_logic[name][0])
                if ocr_str_or_list is None and license_en == consts.AFC_CONTRACT_EN \
                        and is_gsyh is True and name in consts.CON_BANK_FIELD:
                    result = consts.RESULT_Y
                    ocr_str = empty_str
                    reason = compare_logic[name][3]
                elif isinstance(ocr_str_or_list, str) or isinstance(ocr_str_or_list, list):
                    if is_gsyh is True and name in consts.CON_BANK_FIELD:
                        update_args = {'is_gsyh': is_gsyh}
                        for k, v in compare_logic[name][2].items():
                            update_args[k] = v
                    else:
                        update_args = compare_logic[name][2]
                    if isinstance(ocr_str_or_list, list):
                        ocr_str = json.dumps(ocr_str_or_list, ensure_ascii=False)
                    else:
                        ocr_str_or_list = ocr_str_or_list.strip()
                        ocr_str = ocr_str_or_list
                    result = getattr(cp, compare_logic[name][1])(value, ocr_str_or_list, **update_args)
                    reason = compare_logic[name][3]
                else:
                    result = consts.RESULT_N
                    ocr_str = empty_str
                    reason = compare_logic[name][3]

            # img_path = empty_str
            if name not in compare_logic:
                img_path = empty_str
            else:
                img_path = ocr_res.get(consts.IMG_PATH_KEY, {}).get(compare_logic[name][0], empty_str) if result == consts.RESULT_N else empty_str
            error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value
            if isinstance(value, list):
                value = json.dumps(value, ensure_ascii=False)
            result_field_list.append((name, value, result, ocr_str, img_path, error_type, reason))
    else:
        for name, value in strip_list:
            if isinstance(value, list):
                value = json.dumps(value, ensure_ascii=False)
            result_field_list.append((name, value, consts.RESULT_N, empty_str, empty_str, ErrorType.NF.value,
                                      '{0}未找到'.format(license_en)))

    if ocr_res_str is not None:
        img_map = {}
        for name, _, result, _, img_path, _, _ in result_field_list:
            if result == consts.RESULT_N:
                img_map.setdefault(img_path, []).append(name)
        for path, field_list in img_map.items():
            if os.path.exists(path):
                pre, suf = os.path.splitext(path)
                last_img = cv2.imread(path)
                for field_idx, field in enumerate(field_list):
                    try:
                        save_path = '{0}_{1}{2}'.format(pre, str(field_idx), suf)
                        section_position_list = ocr_res.get(consts.ALL_POSITION_KEY, {}).get(field, [])
                        if isinstance(section_position_list, list) and len(section_position_list) == 4:
                            field_img = last_img[section_position_list[1]: section_position_list[3],
                                                 section_position_list[0]: section_position_list[2], :]
                            cv2.imwrite(save_path, field_img)
                            field_img_path_dict[field] = save_path
                        else:
                            field_img_path_dict[field] = path
                    except Exception as e:
                        field_img_path_dict[field] = path

    return result_field_list, field_img_path_dict


def se_mvc34_compare(license_en, ocr_res_dict, field_list):
    ocr_field, compare_logic, _ = consts.SE_COMPARE_FIELD[license_en]
    ocr_res_str = ocr_res_dict.get(ocr_field)

    is_find = False
    result_field_list = []
    field_img_path_dict = dict()

    if ocr_res_str is not None:
        ocr_res_list = json.loads(ocr_res_str)
        length = len(ocr_res_list)

        page34_date_dict = dict()
        first_res = None
        for res_idx in range(length-1, -1, -1):
            if consts.TRANSFER_DATE in ocr_res_list[res_idx]:
                img_path = ocr_res_list[res_idx].get(consts.IMG_PATH_KEY_2, '')
                section_img_path = ocr_res_list[res_idx].get(consts.SECTION_IMG_PATH_KEY_2, '')
                for idx, transfer_date in enumerate(ocr_res_list[res_idx].get(consts.TRANSFER_DATE, [])):
                    try:
                        transfer_name = ocr_res_list[res_idx].get(consts.TRANSFER_NAME, [])[idx]
                    except Exception as e:
                        transfer_name = empty_str
                    try:
                        transfer_num = ocr_res_list[res_idx].get(consts.TRANSFER_NUM, [])[idx]
                    except Exception as e:
                        transfer_num = empty_str
                    try:
                        position_info_date = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY_2, dict()).get(
                            consts.TRANSFER_DATE, [])[idx]
                    except Exception as e:
                        position_info_date = {}
                    try:
                        position_info_name = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY_2, dict()).get(
                            consts.TRANSFER_NAME, [])[idx]
                    except Exception as e:
                        position_info_name = {}
                    try:
                        position_info_num = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY_2, dict()).get(
                            consts.TRANSFER_NUM, [])[idx]
                    except Exception as e:
                        position_info_num = {}
                    core_info = {
                        consts.TRANSFER_NAME: transfer_name,
                        consts.TRANSFER_NUM: transfer_num,
                        consts.TRANSFER_DATE: transfer_date,
                        consts.IMG_PATH_KEY_2: img_path,
                        consts.SECTION_IMG_PATH_KEY_2: section_img_path,
                        consts.ALL_POSITION_KEY: {
                            consts.TRANSFER_NAME: position_info_name,
                            consts.TRANSFER_NUM: position_info_num,
                            consts.TRANSFER_DATE: position_info_date,
                        },
                    }
                    page34_date_dict.setdefault(transfer_date, []).append(core_info)
                    if first_res is None:
                        first_res = core_info

        max_date = None
        for date_tmp in page34_date_dict.keys():
            try:
                max_date_part = time.strptime(date_tmp, "%Y-%m-%d")
            except Exception as e:
                pass
            else:
                if max_date is None or max_date_part > max_date:
                    max_date = max_date_part

        if max_date is not None or first_res is not None:
            is_find = True
            ocr_res = first_res if max_date is None else page34_date_dict[time.strftime('%Y-%m-%d', max_date)][0]
            failed_field = []
            base_img_path = ocr_res.get(consts.IMG_PATH_KEY_2, '')
            for name, value in field_list:
                ocr_str = ocr_res.get(compare_logic[name][0])
                if not isinstance(ocr_str, str):
                    result = consts.RESULT_N
                    ocr_str = empty_str
                else:
                    result = getattr(cp, compare_logic[name][1])(value, ocr_str, **compare_logic[name][2])
                img_path = base_img_path if result == consts.RESULT_N else empty_str
                error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value
                result_field_list.append((name, value, result, ocr_str, img_path, error_type, compare_logic[name][3]))

                if result == consts.RESULT_N:
                    failed_field.append(name)

            section_img_path = ocr_res.get(consts.SECTION_IMG_PATH_KEY_2, '')
            if len(failed_field) > 0 and os.path.exists(section_img_path):
                info = ocr_res.get(consts.ALL_POSITION_KEY, {})
                try:
                    last_img = img_process(section_img_path, {}, 0)
                except Exception as e:
                    for field in failed_field:
                        field_img_path_dict[field] = base_img_path
                else:
                    pre, suf = os.path.splitext(section_img_path)
                    for field in failed_field:
                        try:
                            res_field = compare_logic[field][0]
                            is_valid, coord_tuple = field_build_coordinates(info.get(res_field, {}))
                            if is_valid:
                                save_path = '{0}_{1}{2}'.format(pre, field, suf)
                                field_img = last_img[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :]
                                cv2.imwrite(save_path, field_img)
                                field_img_path_dict[field] = save_path
                            else:
                                field_img_path_dict[field] = base_img_path
                        except Exception as e:
                            field_img_path_dict[field] = base_img_path

    if not is_find:
        for name, value in field_list:
            result_field_list.append((name, value, consts.RESULT_N, empty_str, empty_str, ErrorType.NF.value, '{0}未找到'.format(license_en)))

    return result_field_list, field_img_path_dict


def se_compare_process(compare_info, ocr_res_dict, is_gsyh, is_auto):
    # individualCusInfo
    # corporateCusInfo
    # vehicleInfo
    # bankInfo
    compare_result = []
    total_fields = 0
    failed_count = 0
    successful_at_this_level = True
    failure_reason = {}
    cn_reason_list = []

    for info_key, info_value in compare_info.items():
        if info_key in ['individualCusInfo', 'applicantInformation']:
            for idx, license_list in info_value.items():
                for license_dict in license_list:
                    for license_en, field_list in license_dict.items():
                        strip_list = []
                        for a, b in field_list:
                            if isinstance(b, str):
                                strip_list.append((a, b.strip()))
                            elif isinstance(b, list):
                                c = []
                                for i in b:
                                    if isinstance(i, str):
                                        c.append(i.strip())
                                    else:
                                        c.append(i)
                                strip_list.append((a, c))
                            else:
                                strip_list.append((a, b))
                        failure_field = []
                        result_field_list, no_ocr_result, field_img_path_dict = se_compare_license(license_en, ocr_res_dict, strip_list)
                        for name, value, result, ocr_str, img_path, error_type, cn_reason in result_field_list:
                            if license_en not in consts.SKIP_CARD or not no_ocr_result:
                                total_fields += 1
                                if result == consts.RESULT_N:
                                    failed_count += 1
                                    successful_at_this_level = False
                                    failure_field.append(name)
                                    cn_reason_list.append(cn_reason)
                            compare_result.append(
                                {
                                    consts.HEAD_LIST[0]: info_key,
                                    consts.HEAD_LIST[1]: idx,
                                    consts.HEAD_LIST[2]: license_en,
                                    consts.HEAD_LIST[3]: name,
                                    consts.HEAD_LIST[4]: value,
                                    consts.HEAD_LIST[5]: ocr_str,
                                    consts.HEAD_LIST[6]: result,
                                    consts.HEAD_LIST[7]: field_img_path_dict.get(name, empty_str),
                                    consts.HEAD_LIST[8]: img_path,
                                    consts.HEAD_LIST[9]: error_type,
                                }
                            )
                        if len(failure_field) > 0:
                            failure_reason.setdefault(info_key, []).append(';'.join(failure_field))
        else:
            for license_en, field_list in info_value.items():
                strip_list = []
                for a, b in field_list:
                    if isinstance(b, str):
                        strip_list.append((a, b.strip()))
                    elif isinstance(b, list):
                        c = []
                        for i in b:
                            if isinstance(i, str):
                                c.append(i.strip())
                            else:
                                c.append(i)
                        strip_list.append((a, c))
                    else:
                        strip_list.append((a, b))
                failure_field = []
                if license_en == consts.MVC34_EN:
                    result_field_list, field_img_path_dict = se_mvc34_compare(license_en, ocr_res_dict, strip_list)
                elif license_en in [consts.HIL_CONTRACT_1_EN, consts.HIL_CONTRACT_2_EN, consts.HIL_CONTRACT_3_EN, consts.AFC_CONTRACT_EN]:
                    result_field_list, field_img_path_dict = se_contract_compare(license_en, ocr_res_dict, strip_list, is_gsyh)
                elif license_en == consts.BS_EN:
                    result_field_list, field_img_path_dict = se_bs_compare(license_en, ocr_res_dict, strip_list, is_auto)
                else:
                    result_field_list, _, field_img_path_dict = se_compare_license(license_en, ocr_res_dict, strip_list)

                for name, value, result, ocr_str, img_path, error_type, cn_reason in result_field_list:
                    total_fields += 1
                    if result == consts.RESULT_N:
                        if license_en != consts.MVI_EN or name != consts.SE_NEW_ADD_FIELD[9]:
                            successful_at_this_level = False
                        failed_count += 1
                        failure_field.append(name)
                        if isinstance(cn_reason, str):
                            cn_reason_list.append(cn_reason)
                        elif isinstance(cn_reason, list):
                            cn_reason_list.extend(cn_reason)
                    compare_result.append(
                        {
                            consts.HEAD_LIST[0]: info_key,
                            consts.HEAD_LIST[1]: "0",
                            consts.HEAD_LIST[2]: license_en,
                            consts.HEAD_LIST[3]: name,
                            consts.HEAD_LIST[4]: value,
                            consts.HEAD_LIST[5]: ocr_str,
                            consts.HEAD_LIST[6]: result,
                            consts.HEAD_LIST[7]: field_img_path_dict.get(name, empty_str),
                            consts.HEAD_LIST[8]: img_path,
                            consts.HEAD_LIST[9]: error_type,
                        }
                    )
                if len(failure_field) > 0:
                    failure_reason.setdefault(info_key, []).append(';'.join(failure_field))
    if failed_count == 0:
        failure_reason_str = ''
        cn_failure_reason_str = ''
        bs_failure_reason_str = ''
    else:
        reason_list = []
        for key, value in failure_reason.items():
            if len(value) > 0:
                value_str = json.dumps(value)
                reason_list.append('{0}: {1}'.format(key, value_str))
        failure_reason_str = '、'.join(reason_list)

        tmp_set = set()
        last_cn_reason_list = []
        bs_cn_reason_list = []
        for i in cn_reason_list:
            if i in tmp_set:
                continue
            # elif i in consts.BS_REASON:
            #     tmp_set.add(i)
            #     bs_cn_reason_list.append(i)
            else:
                tmp_set.add(i)
                last_cn_reason_list.append(i)
        cn_failure_reason_str = '\n'.join(last_cn_reason_list)
        bs_failure_reason_str = '\n'.join(bs_cn_reason_list)
    return compare_result, total_fields, failed_count, successful_at_this_level, failure_reason_str, cn_failure_reason_str, bs_failure_reason_str


def se_result_detect(ocr_res_dict):
    detect_list = []
    for license_en in consts.SE_DETECT_CARD:
        ocr_field, _, _ = consts.SE_COMPARE_FIELD[license_en]
        ocr_res_str = ocr_res_dict.get(ocr_field)
        detect_list.append(ocr_res_str is None)
    return detect_list


def se_compare_auto(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, auto_obj):
    try:
        # 比对逻辑
        # detect_list = se_result_detect(ocr_res_dict)
        compare_info, aa_type, is_gsyh = get_se_cms_compare_info_auto(
            last_obj, application_entity)
        compare_result, total_fields, failed_count, successful_at_this_level, failure_reason_str, cn_failure_reason_str, bs_failure_reason_str = se_compare_process(compare_info, ocr_res_dict, is_gsyh, True)
        compare_log.info('{0} [Auto SE] [compare success] [entity={1}] [id={2}] [ocr_res_id={3}] [result={4}]'.format(
            log_base, application_entity, application_id, ocr_res_id, compare_result))
    except Exception as e:
        compare_log.error('{0} [Auto SE] [compare error] [entity={1}] [id={2}] [ocr_res_id={3}] '
                          '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id,
                                               traceback.format_exc()))
    else:
        # 将比对结果写入数据库 auto settlement
        # try:

        auto_obj.aa_type = aa_type
        auto_obj.ocr_auto_result_pass = successful_at_this_level
        # auto_obj.ocr_whole_result_pass = full_result
        auto_obj.ocr_auto_result = json.dumps(compare_result)
        auto_obj.ocr_latest_comparison_time = datetime.now()
        auto_obj.rpa_result = None
        auto_obj.rpa_1st_eye_tat = None
        auto_obj.rpa_2nd_eye_tat = None
        auto_obj.rpa_3rd_eye_tat = None
        auto_obj.rpa_total_tat = None
        auto_obj.rpa_activated_time = None
        auto_obj.rpa_get_case_from_ocr_time = None
        auto_obj.rpa_get_case_from_oc_time = None
        auto_obj.rpa_payment_authorize_time = None
        auto_obj.rpa_second_eye_time = None
        # auto_obj.save()
        # compare_log.info('{0} [Auto SE] [result save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format(
        #     log_base, application_entity, application_id, ocr_res_id))

        # except Exception as e:
        #     compare_log.error('{0} [Auto SE] [result save error] [entity={1}] [id={2}] [ocr_res_id={3}] '
        #                       '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id,
        #                                            traceback.format_exc()))

        return successful_at_this_level


def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, is_cms, auto_result):
    try:
        # 比对逻辑
        start_time = datetime.now()
        detect_list = se_result_detect(ocr_res_dict)
        compare_info, application_version, is_gsyh = get_se_cms_compare_info(
            last_obj, application_entity, detect_list)
        compare_result, total_fields, failed_count, successful_at_this_level, failure_reason_str, cn_failure_reason_str, bs_failure_reason_str = se_compare_process(compare_info, ocr_res_dict, is_gsyh, False)
        compare_log.info('{0} [SE] [compare success] [entity={1}] [id={2}] [ocr_res_id={3}] [result={4}]'.format(
            log_base, application_entity, application_id, ocr_res_id, compare_result))
    except Exception as e:
        compare_log.error('{0} [SE] [compare error] [entity={1}] [id={2}] [ocr_res_id={3}] '
                          '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id,
                                               traceback.format_exc()))
        return False
    else:
        # 将比对结果写入数据库
        try:
            result_table = HILSECompareResult if application_entity == consts.HIL_PREFIX else AFCSECompareResult
            res_obj = result_table.objects.filter(application_id=application_id).first()
            if res_obj is None:
                res_obj = result_table()
                res_obj.application_id = application_id
            res_obj.compare_count = total_fields
            res_obj.failed_count = failed_count
            res_obj.is_finish = successful_at_this_level
            source = consts.INFO_SOURCE[1] if is_cms else consts.INFO_SOURCE[0]
            res_obj.version = '{0}{1}{2}'.format(source, consts.SPLIT_STR, application_version)
            # res_obj.reason1_count = reason1_count
            res_obj.result = json.dumps(compare_result)
            res_obj.update_time = datetime.now()
            res_obj.save()
            compare_log.info('{0} [SE] [result save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format(
                log_base, application_entity, application_id, ocr_res_id))
        except Exception as e:
            compare_log.error('{0} [SE] [result save error] [entity={1}] [id={2}] [ocr_res_id={3}] '
                              '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id,
                                                   traceback.format_exc()))

        # report
        end_time = datetime.now()
        try:
            request_trigger = RequestTrigger.SUBMITING.value if ocr_res_id is None else RequestTrigger.UPLOADING.value
            report_class = HILCompareReport if application_entity == consts.HIL_PREFIX else AFCCompareReport
            report_class.objects.create(
                case_number=application_id,
                request_team=RequestTeam.SETTLEMENT.value,
                request_trigger=request_trigger,
                transaction_start=start_time,
                transaction_end=end_time,
                successful_at_this_level=successful_at_this_level,
                failure_reason=failure_reason_str,
                process_name=ProcessName.SE_CACOMPARE.value,
                total_fields=total_fields,
                workflow_name='' if is_cms else last_obj.customer_type,
            )
            compare_log.info('{0} [SE] [report save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format(
                    log_base, application_entity, application_id, ocr_res_id))
        except Exception as e:
            compare_log.error('{0} [SE] [report save error] [entity={1}] [id={2}] [ocr_res_id={3}] '
                              '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id,
                                                   traceback.format_exc()))

        # cms结果发送
        # if is_cms:
        try:
            application_link = '{0}/showList/showList?entity={1}&scheme={2}&case_id={3}'.format(
                conf.BASE_URL, application_entity, consts.COMPARE_DOC_SCHEME_LIST[1], application_id)
            data = {
                "SubtenantId": consts.TENANT_MAP[application_entity],
                "Data": {
                    "Result_Message": "Pass" if successful_at_this_level else "Fail",
                    "AutoCheckResult": "Pass" if auto_result else "Fail",
                    "Failure_Reason": cn_failure_reason_str,
                    "Application_Number": application_id,
                    "Bank_Statement": bs_failure_reason_str,
                    "Link_URL": application_link,
                    "OCR_Version": 1,
                    "Origin": consts.INFO_SOURCE[1]
                }
            }
            response = cms.send(data)
        except Exception as e:
            compare_log.error('{0} [SE] [cms error] [entity={1}] [id={2}] [ocr_res_id={3}] '
                              '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id,
                                                   traceback.format_exc()))
        else:
            compare_log.info('{0} [SE] [cms success] [entity={1}] [id={2}] [ocr_res_id={3}] [data={4}] '
                             '[response={5}]'.format(log_base, application_entity, application_id, ocr_res_id,
                                                     data, response))

        return successful_at_this_level


@app.task
def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True, is_cms=False):
    # POS: application_id, application_entity, uniq_seq, None
    # OCR: application_id, business_type(application_entity), None, ocr_res_id

    compare_log.info('{0} [receive task] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] [is_ca={5}] '
                     '[is_cms={6}]'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id,
                                           is_ca, is_cms))

    # 根据application_id查找最新的比对信息,如果没有,结束
    if is_ca:
        comparison_class = HILComparisonInfo if application_entity == consts.HIL_PREFIX else AFCComparisonInfo
    else:
        if application_entity == consts.HIL_PREFIX:
            comparison_class = HILSECMSInfo if is_cms else HILSEComparisonInfo
        else:
            comparison_class = AFCSECMSInfo if is_cms else AFCSEComparisonInfo
    last_obj = comparison_class.objects.filter(application_id=application_id).last()
    if last_obj is None:
        compare_log.info('{0} [comparison info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] '
                         '[is_ca={5}] [is_cms]={6}'.format(log_base, application_entity, application_id, uniq_seq,
                                                           ocr_res_id, is_ca, is_cms))
        return

    # 根据application_id查找OCR累计结果指定license字段,如果没有,结束
    if is_ca:
        result_class = HILOCRResult if application_entity == consts.HIL_PREFIX else AFCOCRResult
        ca_ocr_res_dict = dict()
    else:
        result_class = HILSEOCRResult if application_entity == consts.HIL_PREFIX else AFCSEOCRResult
        ca_result_class = HILOCRResult if application_entity == consts.HIL_PREFIX else AFCOCRResult
        # if ocr_res_id is None:
        ca_ocr_res_dict = ca_result_class.objects.filter(application_id=application_id).values(
            *consts.CA_ADD_COMPARE_FIELDS).first()
        # else:
        #     ca_ocr_res_dict = ca_result_class.objects.filter(id=ocr_res_id).values(
        #         *consts.CA_ADD_COMPARE_FIELDS).first()
    if ocr_res_id is None:
        ocr_res_dict = result_class.objects.filter(application_id=application_id).values(*consts.COMPARE_FIELDS).first()
    else:
        ocr_res_dict = result_class.objects.filter(id=ocr_res_id).values(*consts.COMPARE_FIELDS).first()
    if ocr_res_dict is None:
        compare_log.info('{0} [ocr info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] '
                         '[is_ca={5}] [is_cms]={6}'.format(log_base, application_entity, application_id,
                                                           uniq_seq, ocr_res_id, is_ca, is_cms))
        return

    if is_ca:
        ca_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict)
    else:
        for field_name in consts.CA_ADD_COMPARE_FIELDS:
            if isinstance(ca_ocr_res_dict, dict) and isinstance(ca_ocr_res_dict.get(field_name), str):
                tmp_ca_result = json.loads(ca_ocr_res_dict.get(field_name))
                if isinstance(ocr_res_dict.get(field_name), str):
                    tmp_se_result = json.loads(ocr_res_dict.get(field_name))
                    tmp_ca_result.extend(tmp_se_result)
                ocr_res_dict[field_name] = json.dumps(tmp_ca_result)
        # auto settlement
        auto_class = HILAutoSettlement if application_entity == consts.HIL_PREFIX else AFCAutoSettlement
        auto_obj = auto_class.objects.filter(application_id=application_id, on_off=True).first()
        if auto_obj is not None:
            auto_result = se_compare_auto(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, auto_obj)
        else:
            auto_result = None

        full_result = se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, is_cms, auto_result)

        if auto_obj is not None:
            try:
                auto_obj.ocr_whole_result_pass = full_result
                auto_obj.save()
                compare_log.info('{0} [Auto SE] [result save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format(
                    log_base, application_entity, application_id, ocr_res_id))
            except Exception as e:
                compare_log.error('{0} [Auto SE] [result save error] [entity={1}] [id={2}] [ocr_res_id={3}] '
                                  '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id,
                                                       traceback.format_exc()))