package com.supervision.police.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.common.domain.R;
import com.supervision.common.enums.ResultStatusEnum;
import com.supervision.common.exception.CustomException;
import com.supervision.common.utils.ExcelReader;
import com.supervision.common.utils.IPages;
import com.supervision.common.utils.StringUtils;
import com.supervision.police.domain.CasePerson;
import com.supervision.police.domain.ComDictionary;
import com.supervision.police.dto.AtomicIndexDTO;
import com.supervision.police.dto.IndexDetail;
import com.supervision.police.dto.ModelCaseDTO;
import com.supervision.police.mapper.CasePersonMapper;
import com.supervision.police.mapper.ModelCaseMapper;
import com.supervision.police.domain.ModelCase;
import com.supervision.police.service.CaseStatusManageService;
import com.supervision.police.service.ComDictionaryService;
import com.supervision.police.service.ModelCaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

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

/**
 * 案件表(ModelCase)表服务实现类
 *
 * @author qmy
 * @since 2024-07-02 14:51:27
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ModelCaseServiceImpl extends ServiceImpl<ModelCaseMapper, ModelCase> implements ModelCaseService {

    private final ComDictionaryService comDictionaryService;

    private final ModelCaseMapper modelCaseMapper;

    private final CasePersonMapper casePersonMapper;

    private final CaseStatusManageService caseStatusManageService;

    /**
     * 查询列表
     * @param modelCase
     * @param page
     * @param size
     * @return
     */
    @Override
    public IPage<ModelCaseDTO> queryList(ModelCase modelCase, Integer page, Integer size) {
        IPage<ModelCase> modelCaseIPage = modelCaseMapper.selectAll(Page.of(page, size), modelCase);

        if (CollUtil.isEmpty(modelCaseIPage.getRecords())){
            return Page.of(page, size);
        }

        List<String> caseIdList = modelCaseIPage.getRecords().stream().map(ModelCase::getId).toList();

        List<CasePerson> casePersonList = casePersonMapper.selectList(
                Wrappers.lambdaQuery(CasePerson.class).in(CasePerson::getCaseId, caseIdList));
        // 多级分组
        Map<String, Map<String, List<CasePerson>>> persionMap = casePersonList.stream().collect(Collectors.groupingBy(CasePerson::getCaseId,
                Collectors.groupingBy(person -> StrUtil.equals(person.getRoleCode(), "1") ? "1" : "2")));
        List<ComDictionary> dicts = comDictionaryService.list();

        return modelCaseIPage.convert(modelCaseInfo -> {
            ModelCaseDTO modelCaseDTO = BeanUtil.toBean(modelCaseInfo, ModelCaseDTO.class, CopyOptions.create().setIgnoreProperties("lawActor"));
            String[] caseTypes = modelCaseDTO.getCaseType().split(",");
            List<String> caseType = new ArrayList<>();
            for (String type : caseTypes) {
                caseType.add(comDictionaryService.getName(dicts, "case_type", type));
            }
            modelCaseDTO.setCaseTypeName(StringUtils.join(caseType, ","));
            modelCaseDTO.setCaseStatusName(comDictionaryService.getName(dicts, "case_status", modelCaseDTO.getCaseStatus()));
            modelCaseDTO.setCrimeModeName(comDictionaryService.getName(dicts, "crime_mode", modelCaseDTO.getCrimeMode()));
            modelCaseDTO.setIdentifyResultName(comDictionaryService.getName(dicts, "identify_result", modelCaseDTO.getIdentifyResult()));
            Map<String, List<CasePerson>> casePersonMap = persionMap.get(modelCaseDTO.getId());
            if (CollUtil.isNotEmpty(casePersonMap)){
                modelCaseDTO.setLawActor(CollUtil.getFirst(casePersonMap.get("1")));
                modelCaseDTO.floatLawActorInfo();
                modelCaseDTO.setLawPartyList(casePersonMap.get("2"));
            }
            return modelCaseDTO;
        });
    }

    /**
     * 行为人,当事人信息
     * @param lawActor
     * @param lawParty
     */
    record lawActorPartyPair(String lawActor, String lawParty){}

    @Override
    public R<?> checkCaseNo(String caseNo,String caseId) {
        Long count = modelCaseMapper.selectCount(new LambdaQueryWrapper<ModelCase>()
                .eq(ModelCase::getCaseNo, caseNo)
                .eq(ModelCase::getDataStatus, "1")
                .ne(StrUtil.isNotEmpty(caseId), ModelCase::getId, caseId));
        if (count == 0) {
            return R.ok(caseNo);
        } else {
            return R.okMsg("案件编号已存在,请勿重复添加");
        }
    }

    @Override
    public R<?> addOrUpd(ModelCase modelCase) {
        int i = 0;
        if (modelCase.getId() != null) {
            i = modelCaseMapper.updateById(modelCase);
        } else {
            Long num = modelCaseMapper.selectCount(null);
            modelCase.setIndexNum(Integer.parseInt(num.toString()) + 1);
            i = modelCaseMapper.insert(modelCase);
        }
        if (i > 0) {
            return R.okMsg("保存成功");
        } else {
            return R.fail("保存失败");
        }
    }

    @Override
    public R<?> del(String id) {
        ModelCase modelCase = modelCaseMapper.selectById(id);
        modelCase.setDataStatus(StringUtils.getUUID());
        int i = modelCaseMapper.updateById(modelCase);
        if (i > 0) {
            return R.okMsg("删除成功");
        } else {
            return R.fail("删除失败");
        }
    }

    @Override
    public R<List<CasePerson>> getPerson(String caseId, String name) {
        LambdaQueryWrapper<CasePerson> wrapper = Wrappers.lambdaQuery();
        wrapper.like(CasePerson::getCaseId, caseId)
                .like(CasePerson::getName, name);
        List<CasePerson> casePeople = casePersonMapper.selectList(wrapper);
        List<ComDictionary> dicts = comDictionaryService.list();
        for (CasePerson cp : casePeople) {
            cp.setRoleName(comDictionaryService.getName(dicts, "case_role", cp.getRoleCode()));
        }
        return R.ok(casePeople);
    }

    @Override
    @Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
    public R<?> addPersion(CasePerson person) {
        int i = casePersonMapper.insert(person);
        if (i > 0) {
            caseStatusManageService.whenSaveCasePeople(person.getCaseId(), person.getRoleCode());
            return R.okMsg("新增成功");
        } else {
            return R.fail("新增失败");
        }
    }

    @Override
    public R<?> uploadCase(MultipartFile file) {
        /**
         * 检查文件格式
         */
        String fileName = file.getOriginalFilename();
        assert fileName != null;
        // 截取文件的类型符
        String substring = fileName.substring(fileName.lastIndexOf(".") + 1);
        if (!("xls".equals(substring) || "xlsx".equals(substring))) {
            throw new CustomException(ResultStatusEnum.INCORRECT_FILE_FORMAT);// 响应“文件格式不正确”异常
        }
        List<ModelCase> putList = new ArrayList<>();
        try {
            putList = ExcelReader.getCaseList(file.getInputStream(), substring, null);
        } catch (IOException e) {
            e.printStackTrace();
            throw new CustomException(ResultStatusEnum.UPLOAD_EXCEPTION);// 响应“文件上传异常”错误
        }
        List<ComDictionary> dicts = comDictionaryService.list();
        /**
         * 读取bean列表,导入到数据库中
         */
        List<Map<String, Object>> errorList = new ArrayList<>();
        int index = modelCaseMapper.selectMaxIndex() + 1;
        int add = 0;
        for (ModelCase modelCase : putList) {
            if (StringUtils.isEmpty(modelCase.getCaseNo()) || StringUtils.isEmpty(modelCase.getCaseName())
                    || StringUtils.isEmpty(modelCase.getCaseTypeName()) || StringUtils.isEmpty(modelCase.getCaseStatusName())
                    || StringUtils.isEmpty(modelCase.getCrimeModeName())) {
                errorList.add(errorMapBuilder(modelCase, "必填项为空"));
                continue;
            }
            //替换字典项
            String[] split = modelCase.getCaseTypeName().split(",");
            List<String> caseTypes = new ArrayList<>();
            for (String type : split) {
                caseTypes.add(comDictionaryService.getValue(dicts, "case_type", type));
            }
            modelCase.setCaseType(StringUtils.join(caseTypes, ","));
            modelCase.setCaseStatus(comDictionaryService.getValue(dicts, "case_status", modelCase.getCaseStatusName()));
            modelCase.setCrimeMode(comDictionaryService.getValue(dicts, "crime_mode", modelCase.getCrimeModeName()));
            modelCase.setIndexNum(index);
            modelCaseMapper.insert(modelCase);
            add++;
            index++;
        }
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("errorList", errorList);
        returnMap.put("add", add);
        return R.ok(returnMap);
    }

    private Map<String, Object> errorMapBuilder(ModelCase modelCase, String errorText) {
        return new HashMap<String, Object>(2) {{
            put("caseNo", modelCase.getCaseNo());
            put("caseName", modelCase.getCaseName());
            put("errorText", errorText);
        }};
    }

    @Override
    public R<?> getIndexDetail(String caseId, String indexType, Integer page, Integer size) {
        IPage<IndexDetail> iPage = new Page<>(page, size);
        iPage = modelCaseMapper.getIndexDetail(iPage, caseId, indexType);
        List<IndexDetail> records = iPage.getRecords();
        for (IndexDetail record : records) {
            if (StringUtils.isEmpty(record.getAtomicIds())){
                continue;
            }
            String[] array = record.getAtomicIds().split(",");
            List<String> atomicIds = Arrays.asList(array);
            List<AtomicIndexDTO> atomics = modelCaseMapper.getAtomicDetail(caseId, atomicIds);
            record.setChildren(atomics);
        }
        iPage.setRecords(records);
        return R.ok(IPages.buildDataMap(iPage));
    }

}