package com.yeejoin.amos.boot.module.tcm.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.module.common.api.dto.TzsUserPermissionDto;
import com.yeejoin.amos.boot.module.common.api.entity.TzsUserPermission;
import com.yeejoin.amos.boot.module.tcm.api.dto.TzsUserInfoDto;
import com.yeejoin.amos.boot.module.tcm.api.mapper.TzsUserPermissionMapper;
import com.yeejoin.amos.boot.module.tcm.api.service.ITzsUserPermissionService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.*;

/**
 * 用户资质信息表服务实现类
 *
 * @author system_generator
 * @date 2024-08-27
 */
@Service
public class TzsUserPermissionServiceImpl extends BaseService<TzsUserPermissionDto, TzsUserPermission, TzsUserPermissionMapper> implements ITzsUserPermissionService {
    /**
     * 检验人员资质类型
     */
    private final String JYRY_TYPE = "permissionData66151";
    /**
     * 检测人员资质类型
     */
    private final String JCRY_TYPE = "permissionData66152";
    /**
     * 工作人员资质类型
     */
    private final String ZYRY_TYPE = "permissionData6552";

    /**
     * 需要转换的附件字段 jsonString化字段
     */
    private final String[] ATTACHMENTS = {"certAttachment", "itemCode", "permissionItem"};

    /**
     * 分页查询
     */
    public Page<TzsUserPermissionDto> queryForTzsUserPermissionPage(Page<TzsUserPermissionDto> page) {
        return this.queryForPage(page, null, false);
    }

    /**
     * 列表查询 示例
     */
    public List<TzsUserPermissionDto> queryForTzsUserPermissionList() {
        return this.queryForList("", false);
    }

    /**
     * 更新资质权限数据
     */
    @Transactional(rollbackFor = Exception.class)
    public void updatePermissionData(TzsUserInfoDto tzsUserInfo) {
        // 1，删除对应资质
        LambdaQueryWrapper<TzsUserPermission> lambda = new QueryWrapper<TzsUserPermission>().lambda();
        lambda.eq(TzsUserPermission::getUserSeq, tzsUserInfo.getSequenceNbr());
        this.getBaseMapper().delete(lambda);
        // 2，保存对应资质
        this.savePermissionData(tzsUserInfo);
    }

    /**
     * 保存资质权限数据
     */
    @Transactional(rollbackFor = Exception.class)
    public void savePermissionData(TzsUserInfoDto userInfoDto) {

        ArrayList<TzsUserPermission> tzsUserPermissions = new ArrayList<>();
        // permissionData66151 检验资质
        JSONArray permissionData66151 = userInfoDto.getPermissionData66151();
        if (!ValidationUtil.isEmpty(permissionData66151)) {
            permissionData66151.forEach(x -> tzsUserPermissions.add(buildPermission(JYRY_TYPE, (JSONObject) x, userInfoDto)));
        }
        // permissionData66152 检测资质
        JSONArray permissionData66152 = userInfoDto.getPermissionData66152();
        if (!ValidationUtil.isEmpty(permissionData66152)) {
            permissionData66152.forEach(x -> tzsUserPermissions.add(buildPermission(JCRY_TYPE, (JSONObject) x, userInfoDto)));
        }
        // permissionData6552 作业人员资质
        JSONArray permissionData6552 = userInfoDto.getPermissionData6552();
        if (!ValidationUtil.isEmpty(permissionData6552)) {
            permissionData6552.forEach(item -> {
                JSONObject itempermissionData6552 = (JSONObject) item;
                // 前端无法处理后端手动判断
                // 作业项目中含有【金属焊接操作】，则【金属焊接操作-项目代号】必填
                // 作业项目中含有【非金属焊接操作】，则【非金属焊接操作-项目代号】必填
                // 作业项目中含有【其他】，则【其他作业项目是必填的】必填
                String jobItem = String.valueOf(itempermissionData6552.get("jobItem"));
                String otherItem = String.valueOf(itempermissionData6552.get("otherItem"));
                JSONObject itemCode = JSON.parseObject(String.valueOf(itempermissionData6552.get("itemCode")));
                if (jobItem.contains("金属焊接操作") && ObjectUtils.isEmpty(itemCode.get("JSHJCZItemCode"))) {
                    throw new BadRequest("作业项目中含有金属焊接操作，需填写金属焊接操作-项目代号");
                }
                if (jobItem.contains("非金属焊接操作") && ObjectUtils.isEmpty(itemCode.get("FJSHJCZItemCode"))) {
                    throw new BadRequest("作业项目中含有非金属焊接操作，需填写非金属焊接操作-项目代号");
                }
                if (jobItem.contains("其他") && ObjectUtils.isEmpty(otherItem)) {
                    throw new BadRequest("作业项目中含有其他，需填写其他作业项目");
                }
                tzsUserPermissions.add(buildPermission(ZYRY_TYPE, itempermissionData6552, userInfoDto));
            });
        }
        this.saveBatch(tzsUserPermissions);
    }

    /**
     * 构建资质信息实体
     *
     * @param type           人员资质类型
     * @param permissionData 入参
     * @param userInfo       人员信息
     * @return permission
     */
    private TzsUserPermission buildPermission(String type, JSONObject permissionData, TzsUserInfoDto userInfo) {

        TzsUserPermission permission = new TzsUserPermission();
        permission.setUserSeq(userInfo.getSequenceNbr());
        permission.setPermissionLevel(!ZYRY_TYPE.equals(type) ? (String) permissionData.get("permissionLevel") : null);
        permission.setPermissionItem(!ZYRY_TYPE.equals(type) ? JSONObject.toJSONString(permissionData.get("permissionItem"), SerializerFeature.WriteMapNullValue, SerializerFeature.DisableCircularReferenceDetect) : null);
        permission.setPermissionPost(type);
        permission.setCertNo((String) permissionData.get("certNo"));

        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendPattern("yyyy-MM-dd")
                .optionalStart()
                .appendPattern(" HH:mm:ss")
                .optionalEnd()
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                .toFormatter();

        String expiryDateString = String.valueOf(Optional.ofNullable(permissionData.get("expiryDate")).orElse(""));
        if (!ValidationUtil.isEmpty(expiryDateString)) {
            LocalDate localDate1 = LocalDate.parse(expiryDateString, formatter);
            LocalDateTime localDateTime1 = localDate1.atStartOfDay();
            Date expiryDate = Date.from(localDateTime1.atZone(ZoneId.systemDefault()).toInstant());
            permission.setExpiryDate(expiryDate);
        }

        String issueDateString = String.valueOf(Optional.ofNullable(permissionData.get("issueDate")).orElse(""));
        if (!ValidationUtil.isEmpty(issueDateString)) {
            LocalDate localDate2 = LocalDate.parse(issueDateString, formatter);
            LocalDateTime localDateTime2 = localDate2.atStartOfDay();
            Date issueDate = Date.from(localDateTime2.atZone(ZoneId.systemDefault()).toInstant());
            permission.setIssueDate(issueDate);
        }

        permission.setApprovedOrgan((String) permissionData.get("approvedOrgan"));
        permission.setCertAttachment(JSONArray.toJSONString(permissionData.get("certAttachment")));
        permission.setCertType(ZYRY_TYPE.equals(type) ? String.valueOf(permissionData.get("certType")) : null);
        permission.setJobItem(ZYRY_TYPE.equals(type) ? String.valueOf(permissionData.get("jobItem")) : null);
        permission.setOtherItem(ZYRY_TYPE.equals(type) ? (String) permissionData.get("otherItem") : null);
        permission.setItemCode(ZYRY_TYPE.equals(type) ? JSONArray.toJSONString(permissionData.get("itemCode")) : null);
        return permission;
    }

    /**
     * 根据人员的seq 组织可供子表单使用的资质信息数据
     *
     * @param userSeq 人员的seq
     * @return result
     */
    public Map<? extends String, ?> queryForSubFormByUserSeq(String userSeq) {
        Map<String, List<JSONObject>> result = new HashMap<>();
        List<JSONObject> JYRYList = new ArrayList<>();
        List<JSONObject> JCRYList = new ArrayList<>();
        List<JSONObject> ZYRYList = new ArrayList<>();

        LambdaQueryWrapper<TzsUserPermission> lambda = new QueryWrapper<TzsUserPermission>().lambda();
        lambda.eq(TzsUserPermission::getUserSeq, userSeq);
        List<TzsUserPermission> permissionList = this.getBaseMapper().selectList(lambda);

        for (TzsUserPermission permission : permissionList) {
            String permissionPost = permission.getPermissionPost();

            if (JYRY_TYPE.equals(permissionPost)) {
                JYRYList.add(this.convertPermissionToJson(permission));
                continue;
            }
            if (JCRY_TYPE.equals(permissionPost)) {
                JCRYList.add(this.convertPermissionToJson(permission));
                continue;
            }
            if (ZYRY_TYPE.equals(permissionPost)) {
                ZYRYList.add(this.convertPermissionToJson(permission));
            }
        }
        result.putIfAbsent(JYRY_TYPE, JYRYList);
        result.putIfAbsent(JCRY_TYPE, JCRYList);
        result.putIfAbsent(ZYRY_TYPE, ZYRYList);
        return result;
    }

    /**
     * 实体转化为jsonObject 并转化附件
     *
     * @param permission 入参
     * @return result
     */
    public JSONObject convertPermissionToJson(TzsUserPermission permission) {
        JSONObject json = (JSONObject) JSONObject.toJSON(permission);
        for (String field : ATTACHMENTS) {
            if (json.get(field) != null && json.get(field) instanceof String) {
                json.put(field, JSON.parse(json.get(field).toString()));
            }
        }
        // 作业项目【jobItem】 字段特殊处理
        JSONArray jobItem = JSON.parseArray(String.valueOf(json.get("jobItem")));
        json.put("jobItem", jobItem);
        return json;
    }

}