package cn.stylefeng.workflow.instance.modular.task.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.file.api.FileInfoApi;
import cn.stylefeng.roses.kernel.file.api.pojo.AntdvFileInfo;
import cn.stylefeng.team.form.api.FormModelServiceApi;
import cn.stylefeng.team.form.api.entity.FormItem;
import cn.stylefeng.team.form.api.enums.FormComponentEnum;
import cn.stylefeng.team.form.api.enums.FormTypeEnum;
import cn.stylefeng.team.form.api.pojo.FormDesignVo;
import cn.stylefeng.team.project.api.FormDataServiceApi;
import cn.stylefeng.team.project.api.pojo.BusinessRenderDetailVo;
import cn.stylefeng.team.project.api.pojo.request.BusinessDataRequest;
import cn.stylefeng.workflow.api.DefinitionApi;
import cn.stylefeng.workflow.api.entity.instance.RuntimeInstance;
import cn.stylefeng.workflow.api.pojo.config.model.ModelForm;
import cn.stylefeng.workflow.instance.api.InstanceApi;
import cn.stylefeng.workflow.instance.modular.task.pojo.request.TaskFormFileRequest;
import cn.stylefeng.workflow.instance.modular.task.service.FormFileService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONPath;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

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

@Service
public class FormFileServiceImpl implements FormFileService {

    @Resource
    private InstanceApi instanceApi;

    @Resource
    private DefinitionApi definitionApi;

    @Resource
    private FormModelServiceApi formModelServiceApi;

    @Resource
    private FormDataServiceApi formDataServiceApi;

    @Resource
    private FileInfoApi fileInfoApi;

    @Override
    public List<AntdvFileInfo> getInstanceFileList(TaskFormFileRequest taskFormFileRequest) {

        RuntimeInstance runtimeInstance = instanceApi.getInstanceInfById(taskFormFileRequest.getInstanceId());

        List<FormDesignVo> instanceFormDefinitionList = this.getInstanceFormDefinitionList(runtimeInstance);
        if (ObjectUtil.isEmpty(instanceFormDefinitionList)) {
            return new ArrayList<>();
        }

        Map<Long, List<String>> formPicAndFileFieldNameList = this.getFormPicAndFileFieldNameList(instanceFormDefinitionList);
        if (ObjectUtil.isEmpty(formPicAndFileFieldNameList)) {
            return new ArrayList<>();
        }

        Set<Long> formDataFileIdList = getFormDataFileIdList(runtimeInstance, instanceFormDefinitionList, formPicAndFileFieldNameList);
        if (ObjectUtil.isEmpty(formDataFileIdList)) {
            return new ArrayList<>();
        }

        return fileInfoApi.buildAntdvFileInfoBatch(new ArrayList<>(formDataFileIdList));
    }

    private List<FormDesignVo> getInstanceFormDefinitionList(RuntimeInstance runtimeInstance) {

        Long definitionId = runtimeInstance.getDefinitionId();
        List<ModelForm> modelFormList = this.definitionApi.getDefinitionFormDefinitionIdList(definitionId);
        if (ObjectUtil.isEmpty(modelFormList)) {
            return new ArrayList<>();
        }

        Integer formType = modelFormList.get(0).getFormType();

        if (!FormTypeEnum.APP_DESIGN.getValueType().equals(formType)) {
            return new ArrayList<>();
        }

        List<Long> formDefinitionIdList = modelFormList.stream().map(ModelForm::getFormDefinitionId).collect(Collectors.toList());

        return formModelServiceApi.getFromDesignListWithMobileCondition(formDefinitionIdList, true);
    }

    private Map<Long, List<String>> getFormPicAndFileFieldNameList(List<FormDesignVo> formDesignVoList) {

        Map<Long, List<String>> formPicAndFileFieldMap = new HashMap<>();

        for (FormDesignVo formDesignVo : formDesignVoList) {

            Long formDefinitionId = formDesignVo.getFormDefinitionId();

            List<String> fieldNameList = new ArrayList<>();

            List<FormItem> formItemList = formDesignVo.getFormItemList();
            for (FormItem formItem : formItemList) {

                addFormItemFileOrPic(fieldNameList, formItem, null);
            }

            if (ObjectUtil.isNotEmpty(fieldNameList)) {
                formPicAndFileFieldMap.put(formDefinitionId, fieldNameList);
            }
        }

        return formPicAndFileFieldMap;
    }

    private Set<Long> getFormDataFileIdList(RuntimeInstance runtimeInstance, List<FormDesignVo> instanceFormDefinitionList, Map<Long, List<String>> formPicAndFileFieldNameList) {
        BusinessDataRequest businessDataRequest = new BusinessDataRequest();
        businessDataRequest.setPrimaryKeyId(runtimeInstance.getBizPrimaryKey());
        businessDataRequest.setFormDefinitionIdList(instanceFormDefinitionList.stream().map(FormDesignVo::getFormDefinitionId).collect(Collectors.toList()));
        BusinessRenderDetailVo businessRenderDetail = formDataServiceApi.getBusinessRenderDetail(businessDataRequest);
        Map<String, Map<String, Object>> formDetail = businessRenderDetail.getFormDetail();

        Set<Long> fileIdList = new HashSet<>();
        for (Map.Entry<Long, List<String>> entry : formPicAndFileFieldNameList.entrySet()) {
            Long formDefinitionId = entry.getKey();
            List<String> fileFieldCodeList = entry.getValue();

            Map<String, Object> definitionFormData = formDetail.get(formDefinitionId.toString());
            String definitionFormDataJsonString = JSON.toJSONString(definitionFormData);

            for (String fieldName : fileFieldCodeList) {

                Object fieldValue = JSONPath.read(definitionFormDataJsonString, "$." + fieldName);

                if (fieldValue instanceof String) {
                    List<Long> tempFileIdList = JSON.parseArray(fieldValue.toString(), Long.class);
                    fileIdList.addAll(tempFileIdList);
                } else if (fieldValue instanceof List) {
                    List<String> tempFileIdList = (List<String>) fieldValue;
                    if (ObjectUtil.isNotEmpty(tempFileIdList)) {
                        for (String tableFileItem : tempFileIdList) {
                            List<Long> tableFileList = JSON.parseArray(tableFileItem, Long.class);
                            fileIdList.addAll(tableFileList);
                        }
                    }
                }
            }
        }

        return fileIdList;
    }

    private void addFormItemFileOrPic(List<String> fieldNameList, FormItem formItem, String parentFieldName) {
        if (formItem == null) {
            return;
        }

        String prefix = "";
        if (StrUtil.isNotEmpty(parentFieldName)) {
            prefix = parentFieldName + ".";
        }

        if (FormComponentEnum.UPLOAD.getComponentCode().equals(formItem.getComponentCode())) {
            fieldNameList.add(prefix + formItem.getFieldCode());
        } else if (FormComponentEnum.UPLOAD_PIC.getComponentCode().equals(formItem.getComponentCode())) {
            fieldNameList.add(prefix + formItem.getFieldCode());
        }

        List<FormItem> tableItemList = formItem.getChildren();
        if (ObjectUtil.isNotEmpty(tableItemList)) {
            for (FormItem tableFormItem : tableItemList) {
                addFormItemFileOrPic(fieldNameList, tableFormItem, prefix + formItem.getFieldCode());
            }
        }

    }

}
